home *** CD-ROM | disk | FTP | other *** search
/ Magnum One / Magnum One (Mid-American Digital) (Disc Manufacturing).iso / d12 / xms206.arc / OEMSRC.ARC / HIMEM.ASM < prev    next >
Assembly Source File  |  1989-04-04  |  84KB  |  2,829 lines

  1. ;*****************************************************************************
  2. ;*                                         *
  3. ;*  HIMEM.ASM -                            Chip Anderson    *
  4. ;*                                         *
  5. ;*    Extended Memory Specification Driver -                     *
  6. ;*        Copyright 1988, Microsoft Corporation                 *
  7. ;*                                         *
  8. ;*    The HMA was originally envisioned by Ralph Lipe.             *
  9. ;*    Original XMS spec designed by Aaron Reynolds, Chip Anderson, and     *
  10. ;*    Tony Gosling.  Additional spec suggestions by Phil Barrett and David *
  11. ;*    Weise of Microsoft, Ed McNierney of Lotus and Bob Smith of Qualitas. *
  12. ;*                                         *
  13. ;*    MoveExtMemory function written by Tony Gosling.                 *
  14. ;*                                         *
  15. ;*    AT&T 6300 support added by Bill Hall, Olivetti ATC, Cupertino, CA    *
  16. ;*    HP Vectra support added by Ralph Peterson, Hewlett Packard Corp.     *
  17. ;*                                         *
  18. ;*****************************************************************************
  19.  
  20. XMSVersion    equ    0200h
  21. HimemVersion    equ    0206h
  22.  
  23. ; Version -
  24. ;
  25. ;   1.00    - Written                    4/17/88
  26. ;   1.01    - Added Global/Temporary Enable of A20        4/18/88
  27. ;   1.02    - Don't use DOS to change interrupts        4/19/88
  28. ;        - Return 1 for success in Disable cases        4/19/88
  29. ;        - Prevent disables if A20 enabled at start    4/19/88
  30. ;        - Added INT 2F handler check            4/19/88
  31. ;        - Used smarter hooking routine            4/19/88
  32. ;   1.03    - Optimized some code                4/20/88
  33. ;        - Temporarily Disable properly            4/20/88
  34. ;        - Disable INT's while changing vars        4/20/88
  35. ;   1.04    - Check to see if A20 works during init        4/23/88
  36. ;        - Fixed PS/2 support                4/23/88
  37. ;   1.05    - Added QueryExtMemory and AllocExtMemory    4/25/88
  38. ;   1.06    - Never remove the INT 15h hook once it is in    4/27/88
  39. ;        - Changed ExtMemory calls to provide "full" MM    4/27/88
  40. ;        - Force A20 line off on PS2's at init time    4/27/88
  41. ;   1.07    - Added Multiple A20 Handler support        5/01/88
  42. ;        - Added popff macro                5/01/88
  43. ;        - REP MOVSW words not bytes            5/04/88
  44. ;   1.08    - Made popff relocateable            5/04/88
  45. ;        - Added support for the AT&T 6300 Plus        5/05/88
  46. ;        - Added support for the HP Vectra        5/06/88
  47. ;   1.09    - Added CEMM recognition code            5/16/88
  48. ;        - Don't automatically trash BX in HMMControl    5/17/88
  49. ;   1.10    - Change PS/2 ID routine to use Watchdog timer    6/02/88
  50. ;        - Changed CEMM recognition string to just VDISK 6/07/88
  51. ;        - Fixed 2 instance bug                6/14/88
  52. ;   1.11    - Changed INT 2F multiplex number to 43h    6/23/88
  53. ;        - Fixed HP Vectra support for older Vectras    6/23/88
  54. ;        - Fixed Block Move register trashing bug    6/25/88
  55. ;   2.00    - Updated to XMS v2.00                7/10/88
  56. ;        - Reworked initialization code            7/12/88
  57. ;        - Reworked reentrancy issues            7/13/88
  58. ;        - Finialized A20 handling            7/14/88
  59. ;        - Added parameter support            7/14/88
  60. ;   2.01    - Official version with Vecta and 6300 support    7/15/88
  61. ;   2.02    - Removed INT 1 from MoveExtMemory        7/19/88
  62. ;        - Fixed minor problems in QueryExtMemory    7/19/88
  63. ;   2.03    - Added 386 Big Mode MoveBlock            8/04/88
  64. ;        - Added Compaq "Built-In" Memory support    8/05/88
  65. ;        - Fixed 64K-free Installation bug        8/05/88
  66. ;        - Change PS/2 detection code yet again        8/08/88
  67. ;   2.04    - Fixed "A20 On" Message bug (ugh)        8/09/88
  68. ;        - Fixed A20 Init testing code            8/09/88
  69. ;        - Cleaned up for publication            8/09/88
  70. ;   2.05    - Bug Fix: Subtract 64K from first EMB for HMA 11/30/88
  71. ;        - Bug Fix: Check for NUMHANDLES=0 case           12/14/88
  72. ;   2.06    - Source code update                2/07/89
  73. ;          Bug Fix: Restore 286 initialization code    3/21/89
  74.  
  75.         name    Himem
  76.         title   'HIMEM.SYS - Microsoft XMS Device Driver'
  77.  
  78. ;*--------------------------------------------------------------------------*
  79. ;*    EQUATES                                    *
  80. ;*--------------------------------------------------------------------------*
  81.  
  82. DEFHANDLES        equ    32        ; Default # of EMB handles
  83. MAXHANDLES        equ    128        ; Max # of EMB handles
  84.  
  85. cXMSFunctions        equ    12h        ; = # of last function+1!
  86.  
  87. FREEFLAG        equ    00000001b    ; EMB Flags
  88. USEDFLAG        equ    00000010b
  89. UNUSEDFLAG        equ    00000100b
  90.  
  91. ; XMS Error Codes.
  92. ERR_NOTIMPLEMENTED    equ    080h
  93. ERR_VDISKFOUND        equ    081h
  94. ERR_A20            equ    082h
  95. ERR_GENERAL        equ    08Eh
  96. ERR_UNRECOVERABLE    equ    08Fh
  97.  
  98. ERR_HMANOTEXIST        equ    090h
  99. ERR_HMAINUSE        equ    091h
  100. ERR_HMAMINSIZE        equ    092h
  101. ERR_HMANOTALLOCED    equ    093h
  102.  
  103. ERR_OUTOMEMORY        equ    0A0h
  104. ERR_OUTOHANDLES        equ    0A1h
  105. ERR_INVALIDHANDLE    equ    0A2h
  106. ERR_SHINVALID        equ    0A3h
  107. ERR_SOINVALID        equ    0A4h
  108. ERR_DHINVALID        equ    0A5h
  109. ERR_DOINVALID        equ    0A6h
  110. ERR_LENINVALID        equ    0A7h
  111. ERR_OVERLAP        equ    0A8h
  112. ERR_PARITY        equ    0A9h
  113. ERR_EMBUNLOCKED        equ    0AAh
  114. ERR_EMBLOCKED        equ    0ABh
  115. ERR_LOCKOVERFLOW    equ    0ACh
  116. ERR_LOCKFAIL        equ    0ADh
  117.  
  118. ERR_UMBSIZETOOBIG    equ    0B0h
  119. ERR_NOUMBS        equ    0B1h
  120. ERR_INVALIDUMB        equ    0B2h
  121.  
  122. .386p
  123.  
  124. ; In order to address memory above 1 MB on the AT&T 6300 PLUS, it is
  125. ; necessary to use the special OS-MERGE hardware to activate lines
  126. ; A20 to A23.  However, these lines can be disabled only by resetting
  127. ; the processor.  The address to which to return after reset are placed
  128. ; at 40:A2, noted here as RealLoc1.
  129.  
  130. BiosSeg SEGMENT USE16 AT 40h          ; Used to locate 6300 PLUS reset address
  131.  
  132.         org    00A2h
  133. RealLoc1    dd    0
  134.  
  135. BiosSeg ends
  136.  
  137.  
  138. ; Macro to avoid the 286 POPF bug.  Performs a harmless IRET to simulate a
  139. ;   popf.  Some 286s allow interrupts to sneak in during a real popf.
  140.  
  141. popff        macro
  142.         push    cs
  143.         call    pPPFIRet    ; Defined as the offset of any IRET
  144.         endm
  145.  
  146. ;*--------------------------------------------------------------------------*
  147. ;*        SEGMENT DEFINITION                            *
  148. ;*--------------------------------------------------------------------------*
  149.  
  150. CODE        SEGMENT PARA PUBLIC USE16 'CODE'
  151.  
  152.         assume  cs:code,ds:code,es:code
  153.  
  154.         org        0
  155.  
  156. ; The Driver Header definition.
  157. Header        dd    -1        ; Link to next driver, -1 = end of list
  158.         dw    1010000000000000b
  159.                     ; Device attributes, Non-IBM bit set
  160.         dw    Strategy    ; "Stategy" entry point
  161.         dw    Interrupt   ; "Interrupt" entry point
  162.         db    'XMSXXXX0'  ; Device name
  163.  
  164.  
  165. ;****************************************************************************
  166. ;*                                        *
  167. ;*  Data Structures and Global Variables -                    *
  168. ;*                                        *
  169. ;****************************************************************************
  170.  
  171. ; The driver Request Header structure definition.
  172. ReqHdr struc
  173.     ReqLen    db    ?
  174.     Unit    db    ?
  175.     Command    db    ?
  176.     Status    dw    ?
  177.     Reserved    db    8 dup (?)
  178.     Units    db    ?
  179.     Address    dd    ?
  180.     pCmdLine    dd    ?
  181. ReqHdr ends
  182.  
  183. ; An EMB Handle structure definition.
  184. Handle struc            ; Handle Table Entry
  185.     Flags    db    ?    ; Unused/InUse/Free
  186.     cLock    db    ?    ; Lock count
  187.     Base    dw    ?    ; 32-bit base address in K
  188.     Len        dw    ?    ; 32-bit length in K
  189. Handle ends
  190.  
  191. ; Extended Memory Move Block structure definition.
  192. MoveExtendedStruc struc
  193.     bCount        dd    ?    ; Length of block to move
  194.     SourceHandle    dw    ?    ; Handle for souce
  195.     SourceOffset    dd    ?    ; Offset into source
  196.     DestHandle        dw    ?    ; Handle for destination
  197.     DestOffset        dd    ?    ; Offset into destination
  198. MoveExtendedStruc ends
  199.  
  200. ; The Global variables.
  201. pPPFIRet    dw    PPFIRet ; The offset of an IRET for the POPFF macro
  202. pReqHdr        dd    ?    ; Pointer to MSDOS Request Header structure
  203. pInt15Vector    dw    15h*4,0 ; Pointer to the INT 15 Vector
  204. PrevInt15    dd    0    ; Original INT 15 Vector
  205. PrevInt2F    dd    0    ; Original INT 2F Vector
  206. fHMAInUse    db    0    ; High Memory Control Flag, != 0 -> In Use
  207. fCanChangeA20    db    0    ; A20 Enabled at start?
  208. fHMAMayExist    db    0    ; True if the HMA could exist at init time
  209. fHMAExists    db    0    ; True if the HMA exists
  210. fVDISK        db    0    ; True if a VDISK device was found
  211. EnableCount    dw    0    ; A20 Enable/Disable counter
  212. fGlobalEnable    dw    0    ; Global A20 Enable/Disable flag
  213. KiddValley    dw    0    ; The address of the handle table 
  214. KiddValleyTop    dw    0    ; Points to the end of the handle table
  215. MinHMASize    dw    0        ; /HMAMIN= parameter value
  216. cHandles    dw    DEFHANDLES  ; # of handles to allocate
  217.  
  218. cImplementedFuncs db    cXMSFunctions-3        ; Omit the UMB functions
  219.                         ; and ReallocEMB
  220.  
  221. A20Handler    dw    0    ; Offset of the A20 Handler
  222.  
  223. BIMBase     dw    0    ; Base address and Lenght of remaining Compaq
  224. BIMLength    dw    0    ;   Built-In Memory (set at Init time)
  225.  
  226. MemCorr        dw    0    ; KB of memory at FA0000 on AT&T 6300 Plus.
  227.                 ;      This is used to correct INT 15h,
  228.                 ;      Function 88h return value.
  229. OldStackSeg    dw    0    ; Stack segment save area for 6300 Plus.
  230.                 ;      Needed during processor reset.
  231.  
  232. ;*--------------------------------------------------------------------------*
  233. ;*                                        *
  234. ;*  Strategy -                                    *
  235. ;*                                        *
  236. ;*    Called by MS-DOS when ever the driver is accessed.            *
  237. ;*                                        *
  238. ;*  ARGS:   ES:BX = Address of Request Header                    *
  239. ;*  RETS:   Nothing                                *
  240. ;*  REGS:   Preserved                                *
  241. ;*                                        *
  242. ;*--------------------------------------------------------------------------*
  243.  
  244. Strategy    proc    far
  245.  
  246.         ; Save the address of the request header.
  247.         mov        word ptr cs:[pReqHdr],bx
  248.         mov        word ptr cs:[pReqHdr][2],es
  249.         ret
  250.  
  251. Strategy    endp
  252.  
  253.  
  254. ;*--------------------------------------------------------------------------*
  255. ;*                                        *
  256. ;*  Interrupt -                                    *
  257. ;*                                        *
  258. ;*    Called by MS-DOS immediately after Strategy routine            *
  259. ;*                                        *
  260. ;*  ARGS:   None                                *
  261. ;*  RETS:   Return code in Request Header's Status field            *
  262. ;*  REGS:   Preserved                                *
  263. ;*                                        *
  264. ;*--------------------------------------------------------------------------*
  265.  
  266. Interrupt   proc    far
  267.  
  268.         ; Save the registers including flags.
  269.         push    ax            ; We cannot use pusha\popa because
  270.         push    bx            ;    we could be on an 8086 at this point
  271.         push    cx
  272.         push    dx
  273.         push    ds
  274.         push    es
  275.         push    di
  276.         push    si
  277.         push    bp
  278.         pushf
  279.  
  280.         ; Set DS=CS for access to global variables.
  281.         push    cs
  282.         pop        ds
  283.  
  284.         les        di,[pReqHdr]    ; ES:DI = Request Header
  285.  
  286.         mov     bl,es:[di.Command]    ; Get Function code in BL
  287.  
  288.         or        bl,bl        ; Only Function 00h (Init) is legal
  289.         jz        short IInit
  290.  
  291.         cmp     bl,16        ; Test for "legal" DOS functions
  292.         jle     short IOtherFunc
  293.  
  294. IBogusFunc: mov     ax,8003h        ; Return "Unknown Command"
  295.         jmp     short IExit
  296.  
  297. IOtherFunc: xor     ax,ax        ; Return zero for unsupported functions
  298.         jmp     short IExit
  299.  
  300.         ; Initialize the driver.
  301. IInit:        call    InitDriver
  302.  
  303.         les        di,[pReqHdr]    ; Restore ES:DI = Request Header
  304.  
  305. IExit:        or        ax,0100h        ; Turn on the "Done" bit
  306.         mov        es:[di.Status],ax    ; Store return code
  307.  
  308.         ; Restore the registers.
  309.         popff
  310.         pop        bp
  311.         pop        si
  312.         pop        di
  313.         pop        es
  314.         pop        ds
  315.         pop        dx
  316.         pop        cx
  317.         pop        bx
  318.         pop        ax
  319.         ret
  320.  
  321. Interrupt   endp
  322.  
  323.  
  324. ;*--------------------------------------------------------------------------*
  325. ;*                                        *
  326. ;*  Int2FHandler -                                *
  327. ;*                                        *
  328. ;*    Hooks Function 43h, Subfunction 10h to return the            *
  329. ;*    address of the High Memory Manager Control function.            *
  330. ;*    Also returns 80h if Function 43h, Subfunction 0h is requested.        *
  331. ;*                                        *
  332. ;*  ARGS:   AH = Function, AL = Subfunction                    *
  333. ;*  RETS:   ES:BX = Address of XMMControl function (if AX=4310h)        *
  334. ;*        AL = 80h (if AX=4300)                        *
  335. ;*  REGS:   Preserved except for ES:BX (if AX=4310h)                *
  336. ;*        Preserved except for AL    (if AX=4300h)                *
  337. ;*                                        *
  338. ;*--------------------------------------------------------------------------*
  339.  
  340. Int2FHandler proc   far
  341.  
  342.         sti                    ; Flush any queued interrupts
  343.  
  344.         cmp        ah,43h            ; Function 43h?
  345.         jne     short I2FNextInt
  346.         or        al,al            ; Subfunction 0?
  347.         jne     short I2FNextSub        ; No, continue
  348.  
  349.         ; Indicate that an XMS driver is installed.
  350.         mov        al,80h            ; Return 80h in AL
  351. PPFIRet:    iret                ; Label sets up the POPFF macro
  352.  
  353. I2FNextSub: cmp        al,10h            ; Subfunction 10?
  354.         jne     short I2FNextInt        ; No, goto next handler
  355.  
  356.         ; Return the address of the XMS Control function in ES:BX.
  357.         push    cs
  358.         pop        es
  359.         mov        bx,offset XMMControl
  360.         iret
  361.  
  362.         ; Continue down the Int 2F chain.
  363. I2FNextInt: cli                    ; Disable interrupts again
  364.         jmp        cs:[PrevInt2F]
  365.  
  366. Int2FHandler endp
  367.  
  368.  
  369. ;*--------------------------------------------------------------------------*
  370. ;*                                        *
  371. ;*  ControlJumpTable -                                *
  372. ;*                                        *
  373. ;*    Contains the address for each of the XMS Functions.            *
  374. ;*                                        *
  375. ;*--------------------------------------------------------------------------*
  376.  
  377. ControlJumpTable label word
  378.         dw        Version            ; Function 00h
  379.         dw        RequestHMA            ; Function 01h
  380.         dw        ReleaseHMA            ; Function 02h
  381.         dw        GlobalEnableA20        ; Function 03h
  382.         dw        GlobalDisableA20        ; Function 04h
  383.         dw        LocalEnableA20        ; Function 05h
  384.         dw        LocalDisableA20        ; Function 06h
  385.         dw        IsA20On            ; Function 07h
  386.         dw        QueryExtMemory        ; Function 08h
  387.         dw        AllocExtMemory        ; Function 09h
  388.         dw        FreeExtMemory        ; Function 0Ah
  389.         dw        MoveBlock            ; Function 0Bh
  390.         dw        LockExtMemory        ; Function 0Ch
  391.         dw        UnlockExtMemory        ; Function 0Dh
  392.         dw        GetExtMemoryInfo        ; Function 0Eh
  393.  
  394.         ; We don't implement Realloc in this version.
  395. ;        dw        ReallocExtMemory        ; Function 0Fh
  396.  
  397.         ; We don't implement the UMB functions.
  398. ;        dw        RequestUMB            ; Function 14
  399. ;        dw        ReleaseUMB            ; Function 15
  400.  
  401.  
  402. ;*--------------------------------------------------------------------------*
  403. ;*                                        *
  404. ;*  XMMControl -                                *
  405. ;*                                        *
  406. ;*    Main Entry point for the Extended Memory Manager            *
  407. ;*                                        *
  408. ;*  ARGS:   AH = Function, AL = Optional parm                    *
  409. ;*  RETS:   AX = Function Success Code, BL = Optional Error Code        *
  410. ;*  REGS:   AX, BX, DX and ES may not be preserved depending on function    *
  411. ;*                                        *
  412. ;*  INTERNALLY REENTRANT                            *
  413. ;*                                        *
  414. ;*--------------------------------------------------------------------------*
  415.  
  416. XMMControl  proc   far
  417.  
  418.         jmp        short XCControlEntry    ; For "hookability"
  419.         nop                    ; NOTE: The jump must be a 
  420.         nop                    ;  short jump to indicate
  421.         nop                    ;  the end of any hook chain.
  422.                         ;  The nop's allow a far jump
  423.                         ;  to be patched in.
  424. XCControlEntry:
  425.         ; Preserve the following registers.
  426.         push    cx
  427.         push    si
  428.         push    di
  429.         push    ds
  430.         push    es
  431.         pushf
  432.  
  433.         ; Save DS in ES.
  434.         push    ds
  435.         pop        es            ; NOTE: ES cannot be used for parms!
  436.         
  437.         ; Set DS equal to CS.
  438.         push    cs
  439.         pop        ds
  440.         
  441.         ; Preserve the current function number.
  442.         push    ax
  443.  
  444.         ; Is this a call to "Get XMS Version"?
  445.         or        ah,ah
  446.         jz        short XCCallFunc      ; Yes, don't hook INT 15h yet
  447.         
  448.         ; Is this a valid function number?
  449.         cmp        ah,[cImplementedFuncs]
  450.         jb        short XCCheckHook
  451.         pop        ax            ; No, Un-preserve AX and return an error
  452.         xor        ax,ax
  453.         mov        bl,ERR_NOTIMPLEMENTED
  454.         jmp        short XCExit
  455.  
  456.         ; Is INT 15h already hooked?
  457. XCCheckHook:pushf
  458.         cli                ; This is a critical section
  459.         
  460.         cmp        word ptr [PrevInt15][2],0    ; Is the segment non-zero?
  461.         jne     short XCCheckVD
  462.  
  463.         ; Try to claim all remaining extended memory.
  464.         call    HookInt15
  465.  
  466.         ; Was a VDISK device found?
  467. XCCheckVD:  popff            ; End of critical section
  468.         cmp        [fVDISK],0
  469.         je        short XCCallFunc
  470.         pop        ax            ; Yes, Un-preserve AX and return an error
  471.         xor        ax,ax
  472.         mov        bl,ERR_VDISKFOUND
  473.         xor        dx,dx
  474.         jmp        short XCExit
  475.  
  476.         ; Call the appropriate API function.        
  477. XCCallFunc: pop        ax            ; Restore AX
  478.         mov        al,ah
  479.         xor        ah,ah
  480.         shl        ax,1
  481.         mov        di,ax        ; NOTE: DI cannot be used for parms!
  482.         
  483.         call    word ptr [ControlJumpTable+di]
  484.  
  485.         ; Restore the preserved registers.
  486. XCExit:        popff            ; NOTE: Flags must be restored immediately
  487.         pop        es            ;    after the call to the API functions.
  488.         pop        ds
  489.         pop        di
  490.         pop        si
  491.         pop        cx
  492.         ret
  493.  
  494. XMMControl  endp
  495.  
  496.  
  497. ;*--------------------------------------------------------------------------*
  498. ;*                                        *
  499. ;*  Get XMS Version Number -                    FUNCTION 00h    *
  500. ;*                                        *
  501. ;*    Returns the XMS version number                        *
  502. ;*                                        *
  503. ;*  ARGS:   None                                *
  504. ;*  RETS:   AX = XMS Version Number                        *
  505. ;*        BX = Internal Driver Version Number                    *
  506. ;*        DX = 1 if HMA exists, 0 if it doesn't                *
  507. ;*  REGS:   AX, BX and DX are clobbered                        *
  508. ;*                                        *
  509. ;*  INTERNALLY REENTRANT                            *
  510. ;*                                        *
  511. ;*--------------------------------------------------------------------------*
  512.  
  513. Version        proc    near
  514.  
  515.         mov        ax,XMSVersion
  516.         mov        bx,HimemVersion
  517.         xor        dh,dh
  518.  
  519.         ; Is Int 15h hooked?
  520.         cmp        word ptr [PrevInt15][2],0    ; Is the segment non-zero?
  521.         jne     short VHooked
  522.         mov        dl,[fHMAMayExist]        ; No, return the status at
  523.         ret                    ;  init time.
  524.  
  525. VHooked:    mov        dl,[fHMAExists]        ; Yes, return the real status
  526.         ret
  527.  
  528. Version        endp
  529.  
  530.  
  531. ;*--------------------------------------------------------------------------*
  532. ;*                                        *
  533. ;*  HookInt15 -                                    *
  534. ;*                                        *
  535. ;*    Insert the INT 15 hook                            *
  536. ;*                                        *
  537. ;*  ARGS:   None                                *
  538. ;*  RETS:   None                                *
  539. ;*  REGS:   AX, BX, CS, DI, SI, and Flags are clobbered                *
  540. ;*                                        *
  541. ;*  EXTERNALLY NON-REENTRANT                            *
  542. ;*    Interrupts must be disabled before calling this function.        *
  543. ;*                                        *
  544. ;*--------------------------------------------------------------------------*
  545.  
  546. HookInt15   proc    near
  547.  
  548.         push    es
  549.     
  550.         ; Has a VDISK device been installed?        
  551.         call    IsVDISKIn
  552.         cmp        [fVDISK],0
  553.         je        short HINoVD    ; No, continue
  554.         pop        es            ; Yes, return without hooking
  555.         ret
  556.         
  557. HINoVD:        mov        ah,88h        ; Is 64K of Extended memory around?
  558.         int        15h
  559.         sub        ax,[MemCorr]    ; 6300 Plus may have memory at FA0000h
  560.         cmp        ax,64
  561.         jb        short HIInitMemory    ; Less than 64K free?  Then no HMA.
  562.         mov        [fHMAExists],1
  563.  
  564. HIInitMemory:
  565.         ; Init the first handle to be one huge free block.
  566.         mov        bx,[KiddValley]
  567.         mov        [bx.Flags],FREEFLAG
  568.         mov        [bx.Len],ax
  569.         mov     [bx.Base],1024
  570.  
  571.         ; Reserve room for the HMA if it exists.    11-30-88 ChipA
  572.         cmp        [fHMAExists],0
  573.         je        short HICont
  574.         add     [bx.Base],64
  575.         sub     [bx.Len],64
  576.  
  577.         ; See if any Compaq "Built In Memory" exists.
  578. HICont:     mov     ax,[BIMBase]
  579.         or        ax,ax
  580.         jz        short HIHookEmHorns
  581.  
  582.         mov     cx,[BIMLength]
  583.  
  584.         ; Fill out the next handle entry.
  585.         add     bx,size Handle
  586.         mov        [bx.Flags],FREEFLAG
  587.         mov     [bx.Len],cx
  588.         mov     [bx.Base],ax
  589.  
  590.         ; Save the current INT 15 vector.
  591. HIHookEmHorns:
  592.         les     si,dword ptr pInt15Vector
  593.  
  594.         ; Exchange the old vector with the new one.
  595.         mov        ax,offset Int15Handler
  596.         xchg    ax,es:[si][0]
  597.         mov        word ptr [PrevInt15][0],ax
  598.         mov        ax,cs
  599.         xchg    ax,es:[si][2]
  600.         mov        word ptr [PrevInt15][2],ax
  601.         
  602.         pop        es
  603.         ret
  604.  
  605. HookInt15   endp
  606.  
  607.  
  608. ;*--------------------------------------------------------------------------*
  609. ;*                                        *
  610. ;*  IsVDISKIn -                                    *
  611. ;*                                        *
  612. ;*    Looks for drivers which use the IBM VDISK method of allocating        *
  613. ;*  Extended Memory.  XMS is incompatible with the VDISK method.        *
  614. ;*                                        *
  615. ;*  ARGS:   None                                *
  616. ;*  RETS:   None.  Sets "fVDISK" accordingly                    *
  617. ;*  REGS:   AX, CX, SI, DI and Flags are clobbered                *
  618. ;*                                        *
  619. ;*  INTERNALLY REENTRANT                            *
  620. ;*                                        *
  621. ;*--------------------------------------------------------------------------*
  622.  
  623. pVDISK        label   dword
  624.         dw        00013h
  625.         dw        0FFFFh
  626.         
  627. szVDISK        db        'VDISK'           
  628.  
  629. IsVDISKIn   proc    near
  630.  
  631.         ; Look for "VDISK" starting at the 4th byte of extended memory.
  632.         call    LocalEnableA20        ; Turn on A20
  633.  
  634.         push    ds
  635.         push    es
  636.  
  637.         ; Set up the comparison.
  638.         lds        si,cs:pVDISK
  639.         push    cs
  640.         pop        es
  641.         mov        di,offset szVDISK
  642.         mov        cx,5
  643.         cld
  644.         rep     cmpsb            ; Do the comparison
  645.  
  646.         pop     es                ; Restore ES and DS
  647.         pop     ds
  648.  
  649.         jz        short IVIFoundIt
  650.         mov     [fVDISK],0            ; No VDISK device found
  651.         jmp        short IVIExit
  652.         
  653.         ; "VDISK" was found.
  654. IVIFoundIt: mov        [fVDISK],1
  655.  
  656. IVIExit:    call    LocalDisableA20
  657.         ret                 ; Turn off A20
  658.  
  659. IsVDISKIn   endp
  660.  
  661.  
  662. ;*--------------------------------------------------------------------------*
  663. ;*                                        *
  664. ;*  Int15Handler -                                *
  665. ;*                                        *
  666. ;*    Hooks Function 88h to return zero as the amount of extended        *
  667. ;*    memory available in the system.                        *
  668. ;*                                        *
  669. ;*    Hooks Function 87h and preserves the state of A20 across the        *
  670. ;*    block move.                                *
  671. ;*                                        *
  672. ;*  ARGS:   AH = Function, AL = Subfunction                    *
  673. ;*  RETS:   AX = 0 (if AH == 88h)                        *
  674. ;*  REGS:   AX is clobbered                            *
  675. ;*                                        *
  676. ;*--------------------------------------------------------------------------*
  677.  
  678. I15RegSave  dw        ?
  679.  
  680. Int15Handler proc   far
  681.  
  682.         ; Is this a request for the amount of free extended memory?
  683.         cmp        ah,88h
  684.         jne     short I15HCont    ; No, continue
  685.  
  686.         xor     ax,ax        ; Yes, return zero
  687.         iret
  688.  
  689.         ; Is it a Block Move?
  690. I15HCont:   cmp        ah,87h
  691.         jne     short I15HNext    ; No, continue
  692.  
  693.         ; Int 15h Block Move:
  694.         cli             ; Make sure interrupts are off
  695.  
  696.         ; Store the A20 line's state.
  697.         pusha            ; Preserve the registers
  698.         call    IsA20On
  699.         mov        cs:[I15RegSave],ax
  700.         popa            ; Restore the registers
  701.  
  702.         ; Call the previous Int 15h handler.
  703.         pushf            ; Simualate an interrupt
  704.         call    cs:[PrevInt15]
  705.         pusha            ; Preserve previous handler's return
  706.  
  707.         ; Was A20 on before?
  708.         cmp        cs:[I15RegSave],0
  709.         je        short I15HExit    ; No, continue
  710.         mov     ax,1
  711.         call    cs:[A20Handler]    ; Yes, turn A20 back on
  712.  
  713. I15HExit:   popa            ; Restore the previous handler's return
  714.         iret
  715.  
  716.         ; Continue down the Int 15h chain.
  717. I15HNext:   jmp     cs:[PrevInt15]
  718.  
  719. Int15Handler endp
  720.  
  721.  
  722. ;*--------------------------------------------------------------------------*
  723. ;*                                        *
  724. ;*  RequestHMA -                        FUNCTION 01h    *
  725. ;*                                        *
  726. ;*    Give caller control of the High Memory Area if it is available.        *
  727. ;*                                        *
  728. ;*  ARGS:   DX = HMA space requested in bytes                    *
  729. ;*  RETS:   AX = 1 if the HMA was reserved, 0 otherwise.  BL = Error Code   *
  730. ;*  REGS:   AX, BX and Flags clobbered                        *
  731. ;*                                        *
  732. ;*  INTERNALLY NON-REENTRANT                            *
  733. ;*                                        *
  734. ;*--------------------------------------------------------------------------*
  735.  
  736. RequestHMA  proc   near
  737.  
  738.         cli                ; This is a non-reentrant function.
  739.                     ;    Flags are restored after the return.        
  740.         mov        bl,ERR_HMAINUSE
  741.         cmp        [fHMAInUse],1   ; Is the HMA already allocated?
  742.         je        short RHRetErr
  743.  
  744.         mov        bl,ERR_HMANOTEXIST
  745.         cmp        [fHMAExists],0  ; Is the HMA available?
  746.         je        short RHRetErr
  747.  
  748.         mov        bl,ERR_HMAMINSIZE
  749.         cmp        dx,[MinHMASize] ; Is this guy allowed in?
  750.         jb        short RHRetErr
  751.  
  752.         mov        ax,1
  753.         mov        [fHMAInUse],al  ; Reserve the High Memory Area
  754.         xor     bl,bl        ; Clear the error code
  755.         ret
  756.  
  757. RHRetErr:   xor     ax,ax        ; Return failure with error code in BL
  758.         ret
  759.  
  760. RequestHMA  endp
  761.  
  762.  
  763. ;*--------------------------------------------------------------------------*
  764. ;*                                        *
  765. ;*  ReleaseHMA -                        FUNCTION 02h    *
  766. ;*                                        *
  767. ;*    Caller is releasing control of the High Memory area            *
  768. ;*                                        *
  769. ;*  ARGS:   None                                *
  770. ;*  RETS:   AX = 1 if control is released, 0 otherwise.     BL = Error Code    *
  771. ;*  REGS:   AX, BX and Flags clobbered                        *
  772. ;*                                        *
  773. ;*  INTERNALLY NON-REENTRANT                            *
  774. ;*                                        *
  775. ;*--------------------------------------------------------------------------*
  776.  
  777. ReleaseHMA  proc   near
  778.  
  779.         cli                ; This is a non-reentrant function
  780.         
  781.         ; Is the HMA currently in use?
  782.         mov        al,[fHMAInUse]
  783.         or        al,al
  784.         jz        short RLHRetErr ; No, return error
  785.         
  786.         ; Release the HMA and return success.
  787.         mov        [fHMAInUse],0
  788.         mov        ax,1
  789.         xor        bl,bl
  790.         ret
  791.         
  792. RLHRetErr:  xor        ax,ax
  793.         mov        bl,ERR_HMANOTALLOCED
  794.         ret           
  795.  
  796. ReleaseHMA  endp
  797.  
  798.  
  799. ;*--------------------------------------------------------------------------*
  800. ;*                                        *
  801. ;*  GlobalEnableA20 -                        FUNCTION 03h    *
  802. ;*                                        *
  803. ;*    Globally enable the A20 line                        *
  804. ;*                                        *
  805. ;*  ARGS:   None                                *
  806. ;*  RETS:   AX = 1 if the A20 line is enabled, 0 otherwise.  BL = Error        *
  807. ;*  REGS:   AX, BX and Flags clobbered                        *
  808. ;*                                        *
  809. ;*  INTERNALLY NON-REENTRANT                            *
  810. ;*                                        *
  811. ;*--------------------------------------------------------------------------*
  812.  
  813. GlobalEnableA20 proc near
  814.  
  815.         cli                ; This is a non-reentrant function
  816.  
  817.         ; Is A20 already globally enabled?
  818.         cmp        [fGlobalEnable],1
  819.         je        short GEARet
  820.  
  821.         ; Attempt to enable the A20 line.
  822.         call    LocalEnableA20
  823.         or        ax,ax
  824.         jz        short GEAA20Err
  825.  
  826.         ; Mark A20 as globally enabled.
  827.         mov        [fGlobalEnable],1
  828.  
  829.         ; Return success.
  830. GEARet:        mov        ax,1
  831.         xor        bl,bl
  832.         ret
  833.  
  834.         ; Some A20 error occured.
  835. GEAA20Err:  mov        bl,ERR_A20
  836.         xor        ax,ax
  837.         ret
  838.  
  839. GlobalEnableA20 endp
  840.  
  841.  
  842. ;*--------------------------------------------------------------------------*
  843. ;*                                        *
  844. ;*  GlobalDisableA20 -                        FUNCTION 04h    *
  845. ;*                                        *
  846. ;*    Globally disable the A20 line                        *
  847. ;*                                        *
  848. ;*  ARGS:   None                                *
  849. ;*  RETS:   AX = 1 if the A20 line is disabled, 0 otherwise.  BL = Error    *
  850. ;*  REGS:   AX, BX and Flags are clobbered                    *
  851. ;*                                        *
  852. ;*  INTERNALLY NON-REENTRANT                            *
  853. ;*                                        *
  854. ;*--------------------------------------------------------------------------*
  855.  
  856. GlobalDisableA20 proc near
  857.  
  858.         cli                ; This is a non-reentrant function
  859.  
  860.         ; Is A20 already globally disabled?
  861.         cmp        [fGlobalEnable],0
  862.         je        short GDARet
  863.  
  864.         ; Attempt to disable the A20 line.
  865.         call    LocalDisableA20
  866.         or        ax,ax
  867.         jz        short GDAA20Err
  868.  
  869.         ; Mark A20 as globally disabled.
  870.         mov        [fGlobalEnable],0
  871.  
  872.         ; Return success.
  873. GDARet:        mov        ax,1
  874.         xor        bl,bl
  875.         ret
  876.  
  877.         ; Some A20 error occured.
  878. GDAA20Err:  mov        bl,ERR_A20
  879.         xor        ax,ax
  880.         ret
  881.  
  882. GlobalDisableA20 endp
  883.  
  884.  
  885. ;*--------------------------------------------------------------------------*
  886. ;*                                        *
  887. ;*  LocalEnableA20 -                        FUNCTION 05h    *
  888. ;*                                        *
  889. ;*    Locally enable the A20 line                        *
  890. ;*                                        *
  891. ;*  ARGS:   None                                *
  892. ;*  RETS:   AX = 1 if the A20 line is enabled, 0 otherwise.  BL = Error        *
  893. ;*  REGS:   AX, BX and Flags clobbered                        *
  894. ;*                                        *
  895. ;*  INTERNALLY NON-REENTRANT                            *
  896. ;*                                        *
  897. ;*--------------------------------------------------------------------------*
  898.  
  899. LocalEnableA20 proc near
  900.  
  901.         cli                ; This is a non-reentrant function
  902.         
  903.         cmp        [fCanChangeA20],1    ; Can we change A20?
  904.         jne     short LEARet    ; No, don't touch A20
  905.  
  906.         ; Only actually enable A20 if the count is zero.
  907.         cmp        [EnableCount],0
  908.         jne     short LEAIncIt
  909.  
  910.         ; Attempt to enable the A20 line.
  911.         mov        ax,1
  912.         call    [A20Handler]    ; Call machine-specific A20 handler
  913.         or        ax,ax
  914.         jz        short LEAA20Err
  915.  
  916. LEAIncIt:   inc        [EnableCount]
  917.  
  918.         ; Return success.
  919. LEARet:        mov        ax,1
  920.         xor        bl,bl
  921.         ret
  922.  
  923.         ; Some A20 error occurred.
  924. LEAA20Err:  mov        bl,ERR_A20
  925.         xor        ax,ax
  926.         ret
  927.         
  928. LocalEnableA20 endp
  929.  
  930.  
  931. ;*--------------------------------------------------------------------------*
  932. ;*                                        *
  933. ;*  LocalDisableA20 -                        FUNCTION 06h    *
  934. ;*                                        *
  935. ;*    Locally disable the A20 line                        *
  936. ;*                                        *
  937. ;*  ARGS:   None                                *
  938. ;*  RETS:   AX = 1 if the A20 line is disabled, 0 otherwise.  BL = Error    *
  939. ;*  REGS:   AX, BX and Flags are clobbered                    *
  940. ;*                                        *
  941. ;*  INTERNALLY NON-REENTRANT                            *
  942. ;*                                        *
  943. ;*--------------------------------------------------------------------------*
  944.  
  945. LocalDisableA20 proc near
  946.  
  947.         cli                ; This is a non-reentrant function
  948.         
  949.         cmp        [fCanChangeA20],0    ; Can we change A20?
  950.         je        short LDARet    ; No, don't touch A20
  951.  
  952.         ; Make sure the count's not zero.
  953.         cmp        [EnableCount],0
  954.         je        short LDAA20Err
  955.  
  956.         ; Only actually disable if the count is one.
  957.         cmp        [EnableCount],1
  958.         jne     short LDADecIt
  959.  
  960.         xor        ax,ax
  961.         call    [A20Handler]    ; Call machine-specific A20 handler
  962.         or        ax,ax
  963.         jz        short LDAA20Err
  964.  
  965. LDADecIt:   dec        [EnableCount]
  966.  
  967.         ; Return success.
  968. LDARet:        mov        ax,1
  969.         xor        bl,bl
  970.         ret
  971.  
  972.         ; Some A20 error occurred.
  973. LDAA20Err:  mov     bl,ERR_A20
  974.         xor     ax,ax
  975.         ret
  976.             
  977. LocalDisableA20 endp
  978.  
  979.  
  980. ;*--------------------------------------------------------------------------*
  981. ;*                                        *
  982. ;*  IsA20On -                            FUNCTION 07h    *
  983. ;*                                        *
  984. ;*    Returns the state of the A20 line                    *
  985. ;*                                        *
  986. ;*  ARGS:   None                                *
  987. ;*  RETS:   AX = 1 if the A20 line is enabled, 0 otherwise            *
  988. ;*  REGS:   AX, CX, DI, SI and Flags clobbered                    *
  989. ;*                                        *
  990. ;*  INTERNALLY REENTRANT                            *
  991. ;*                                        *
  992. ;*--------------------------------------------------------------------------*
  993.  
  994. LowMemory   label   dword        ; Set equal to 0000:0080
  995.         dw        00080h
  996.         dw        00000h
  997.  
  998. HighMemory  label   dword
  999.         dw        00090h        ; Set equal to FFFF:0090
  1000.         dw        0FFFFh
  1001.  
  1002. IsA20On        proc    near
  1003.  
  1004.         push    ds
  1005.         push    es
  1006.  
  1007.         lds        si,cs:LowMemory    ; Compare the four words at 0000:0080
  1008.         les        di,cs:HighMemory    ;   with the four at FFFF:0090
  1009.         mov        cx,4
  1010.         cld
  1011.         repe    cmpsw
  1012.  
  1013.         pop        es
  1014.         pop        ds
  1015.         xor        ax,ax
  1016.  
  1017.         jcxz    short IAONoWrap ; Are the two areas the same?
  1018.         inc        ax            ; No, return A20 Enabled
  1019.  
  1020. IAONoWrap:  xor     bl,bl
  1021.         ret                ; Yes, return A20 Disabled
  1022.  
  1023. IsA20On        endp
  1024.  
  1025.  
  1026. ;*--------------------------------------------------------------------------*
  1027. ;*                                        *
  1028. ;*  QueryExtMemory -                        FUNCTION 08h    *
  1029. ;*                                        *
  1030. ;*    Returns the size of the largest free extended memory block in K        *
  1031. ;*                                        *
  1032. ;*  ARGS:   None                                *
  1033. ;*  RETS:   AX = Size of largest free block in K.  BL = Error code        *
  1034. ;*        DX = Total amount of free extended memory in K            *
  1035. ;*  REGS:   AX, BX, DX, DI, SI and Flags clobbered                *
  1036. ;*                                        *
  1037. ;*  INTERNALLY REENTRANT                            *
  1038. ;*                                        *
  1039. ;*--------------------------------------------------------------------------*
  1040.  
  1041. QueryExtMemory proc near
  1042.  
  1043.         ; Init the error code in DL.
  1044.         mov        dl,ERR_OUTOMEMORY
  1045.     
  1046.         ; Scan for the largest block marked FREE.
  1047.         xor        di,di            ; DI = Max. size found so far
  1048.         xor        si,si            ; SI = Total amount of free memory
  1049.         mov        bx,KiddValley
  1050.         mov     cx,[cHandles]        ; Loop through the handle table
  1051. QEMLoop:    cmp        [bx.Flags],FREEFLAG
  1052.         jne     short QEMBottom
  1053.  
  1054.         ; Add this free block to the total.
  1055.         add     si,[bx.Len]         ; CHANGED 7/19/88
  1056.  
  1057.         ; Is this block larger?
  1058.         mov        ax,[bx.Len]
  1059.         cmp        di,ax
  1060.         jae     short QEMBottom        ; CHANGED 7/19/88
  1061.         
  1062.         ; Yes, save it away.
  1063.         mov        di,ax
  1064.         xor     dl,dl            ; We ain't Out o' Memory
  1065.         
  1066. QEMBottom:  add        bx,SIZE Handle
  1067.         loop    QEMLoop
  1068.  
  1069.         ; Setup the return.
  1070.         mov        ax,di
  1071.         mov        bl,dl            ; Retrieve the error code
  1072.         mov     dx,si            ; CHANGED 7/19/88
  1073.         ret
  1074.  
  1075. QueryExtMemory endp
  1076.  
  1077.  
  1078. ;*--------------------------------------------------------------------------*
  1079. ;*                                        *
  1080. ;*  AllocExtMemory -                        FUNCTION 09h    *
  1081. ;*                                        *
  1082. ;*    Reserve a block of extended memory                    *
  1083. ;*                                        *
  1084. ;*  ARGS:   DX = Amount of K being requested                    *
  1085. ;*  RETS:   AX = 1 of successful, 0 otherwise.    BL = Error Code            *
  1086. ;*        DX = 16-bit handle to the allocated block                *
  1087. ;*  REGS:   AX, BX, DX and Flags clobbered                    *
  1088. ;*                                        *
  1089. ;*  INTERNALLY NON-REENTRANT                            *
  1090. ;*                                        *
  1091. ;*--------------------------------------------------------------------------*
  1092.  
  1093. ; Algorithm -
  1094. ;
  1095. ;   Scan the Handle Table looking for BOTH an unused handle and
  1096. ;    a free block which is large enough:
  1097. ;
  1098. ;   1.    If both are found -
  1099. ;        Mark the free block as used and adjust its size.
  1100. ;        Make the unused handle a free block containing the remaining
  1101. ;        unallocated portion of the original free block.
  1102. ;
  1103. ;   2.    If only an unused handle is found -
  1104. ;        We're out of memory.
  1105. ;
  1106. ;   3.    If only a properly sized free block is found -
  1107. ;        We only have one handle left.
  1108. ;        Mark the free block as used.  The requester gets all of the
  1109. ;        block's memory.
  1110. ;
  1111. ;   4.    If neither are found -
  1112. ;        We're out of memory.
  1113.  
  1114. hFreeBlock    dw  ?
  1115. hUnusedBlock    dw  ?
  1116.  
  1117. AllocExtMemory proc near
  1118.  
  1119.         cli             ; This is a non-reentrant function
  1120.         
  1121.         ; Scan the handle table looking for BOTH an unused handle and 
  1122.         ;    a free block which is large enough.
  1123.         xor        ax,ax
  1124.         mov        [hFreeBlock],ax
  1125.         mov        [hUnusedBlock],ax
  1126.         mov        bx,KiddValley
  1127.         mov     cx,[cHandles]    ; Loop through the handle table
  1128.  
  1129.         ; Have we already found a free block which is large enough?
  1130. AEMhLoop:   cmp     [hFreeBlock],0
  1131.         jne     short AEMUnused    ; Yes, see if this one is unused
  1132.         
  1133.         ; Is this block free?
  1134.         cmp     [bx.Flags],FREEFLAG
  1135.         jne     short AEMUnused    ; No, see if it is unused
  1136.         
  1137.         ; Is it large enough?
  1138.         cmp        dx,[bx.Len]
  1139.         ja        short AEMNexth    ; No, get the next handle
  1140.  
  1141.         ; Save this guy away.
  1142.         mov        [hFreeBlock],bx
  1143.         jmp        short AEMBottom
  1144.         
  1145. AEMUnused:  ; Have we already found an unused handle?
  1146.         cmp     [hUnusedBlock],0
  1147.         jne     short AEMNexth    ; Yes, get the next handle
  1148.  
  1149.         ; Is this block unused?
  1150.         cmp     [bx.Flags],UNUSEDFLAG
  1151.         jne     short AEMNexth    ; No, get the next handle
  1152.         
  1153.         ; Save this guy away.
  1154.         mov        [hUnusedBlock],bx
  1155.             
  1156.         ; Have we found what we are looking for?
  1157.         cmp        [hFreeBlock],0
  1158.         je        short AEMNexth
  1159. AEMBottom:  cmp        [hUnusedBlock],0
  1160.         jne     short AEMGotBoth    ; Yes, continue
  1161.         
  1162. AEMNexth:   ; Get the next handle
  1163.         add        bx,SIZE Handle
  1164.         loop    AEMhLoop
  1165.         
  1166.         ; We are at the end of the handle table and we didn't find both
  1167.         ; things we were looking for.  Did we find a free block?
  1168.         mov     si,[hFreeBlock]
  1169.         or        si,si
  1170.         jnz     short AEMRetSuc    ; Yes, Case 3 - Alloc the entire block
  1171.         
  1172.         ; Did we find an unused handle?
  1173.         cmp        [hUnusedBlock],0
  1174.         je        short AEMOOHandles    ; No, Case 4 - We're out of handles
  1175.         
  1176.         ; Case 2 - Is this a request for a zero-length handle?
  1177.         or        dx,dx
  1178.         jnz     short AEMOOMemory    ; No, we're out of memory
  1179.         
  1180.         ; Reserve the zero-length handle.
  1181.         mov        si,[hUnusedBlock]
  1182.         mov        [hFreeBlock],si
  1183.         jmp        short AEMRetSuc
  1184.         
  1185. AEMGotBoth: ; We're at Case 1 above.
  1186.         ;    Mark the free block as used (done below) and adjust its size.
  1187.         ;    Make the unused handle a free block containing the remaining
  1188.         ;       unallocated portion of the original free block.
  1189.         mov        si,[hFreeBlock]
  1190.         mov        di,[hUnusedBlock]
  1191.         
  1192.         ; Unused.Base = Old.Base + request
  1193.         mov        ax,[si].Base
  1194.         add        ax,dx
  1195.         mov        [di].Base,ax
  1196.         
  1197.         ; New.Len = request
  1198.         mov        ax,dx
  1199.         xchg    [si].Len,ax
  1200.         
  1201.         ; Unused.Len = Old.Len - request
  1202.         sub        ax,dx
  1203.         mov        [di].Len,ax
  1204.         mov        [di].Flags,FREEFLAG        ; Unused.Flags = FREE
  1205.         
  1206. AEMRetSuc:  ; Complete the allocation.
  1207.         mov        [si].Flags,USEDFLAG        ; New.Flags = USED
  1208.         mov        dx,[hFreeBlock]
  1209.         mov        ax,1
  1210.         xor        bl,bl
  1211.         ret
  1212.  
  1213. AEMOOMemory:mov        bl,ERR_OUTOMEMORY
  1214.         jmp        short AEMErrRet
  1215.         
  1216. AEMOOHandles:
  1217.         mov        bl,ERR_OUTOHANDLES
  1218. AEMErrRet:  xor        ax,ax            ; Return failure
  1219.         mov        dx,ax
  1220.         ret               
  1221.         
  1222. AllocExtMemory endp
  1223.  
  1224.  
  1225. ;*--------------------------------------------------------------------------*
  1226. ;*                                        *
  1227. ;*  ValidateHandle -                                *
  1228. ;*                                        *
  1229. ;*    Validates an extended memory block handle                *
  1230. ;*                                        *
  1231. ;*  ARGS:   DX = 16-bit handle to the extended memory block            *
  1232. ;*  RETS:   Carry is set if the handle is valid                    *
  1233. ;*  REGS:   Preserved except the carry flag                    *
  1234. ;*                                        *
  1235. ;*--------------------------------------------------------------------------*
  1236.  
  1237. ValidateHandle proc near
  1238.  
  1239.         pusha                ; Save everything
  1240.         mov        bx,dx            ; Move the handle into BX
  1241.  
  1242.         ; The handle must be equal to or above "KiddValley".
  1243.         cmp        bx,[KiddValley]
  1244.         jb        short VHOne
  1245.         
  1246.         ; The handle must not be above "KiddValleyTop".
  1247.         cmp        bx,[KiddValleyTop]
  1248.         ja        short VHOne
  1249.         
  1250.         ; (The handle-"KiddValley") must be a multiple of a handle's size.
  1251.         sub        dx,[KiddValley]
  1252.         mov        ax,dx
  1253.         xor        dx,dx
  1254.         mov        cx,SIZE Handle
  1255.         div        cx                
  1256.         or        dx,dx            ; Any remainder?        
  1257.         jnz     short VHOne         ; Yup, it's bad
  1258.  
  1259.         ; Does the handle point to a currently USED block?
  1260.         cmp        [bx.Flags],USEDFLAG
  1261.         jne     short VHOne         ; This handle is not being used.
  1262.         
  1263.         ; The handle looks good to me...
  1264.         popa                ; Restore everything
  1265.         stc                 ; Return success
  1266.         ret
  1267.  
  1268. VHOne:        ; It's really bad.
  1269.         popa                ; Restore everything
  1270.         clc                 ; Return failure
  1271.         ret
  1272.         
  1273. ValidateHandle endp
  1274.  
  1275.  
  1276. ;*--------------------------------------------------------------------------*
  1277. ;*                                        *
  1278. ;*  FreeExtMemory -                        FUNCTION 0Ah    *
  1279. ;*                                        *
  1280. ;*    Frees a block of extended memory which was allocated via AllocExt   *
  1281. ;*                                        *
  1282. ;*  ARGS:   DX = 16-bit handle to the extended memory block            *
  1283. ;*  RETS:   AX = 1 if successful, 0 otherwise.    BL = Error code            *
  1284. ;*  REGS:   AX, BX, CX, DX, SI, DI and Flags clobbered                *
  1285. ;*                                        *
  1286. ;*  INTERNALLY NON-REENTRANT                            *
  1287. ;*                                        *
  1288. ;*--------------------------------------------------------------------------*
  1289.  
  1290. FreeExtMemory proc near
  1291.  
  1292.         cli                 ; This is a non-reentrant function
  1293.         
  1294.         ; Make sure that the handle is valid.
  1295.         call    ValidateHandle
  1296.         jnc     short FEMBadh
  1297.         mov        si,dx            ; Move the handle into SI
  1298.         
  1299.         ; Make sure that the handle points to a FREE block.
  1300.         cmp        [si].cLock,0
  1301.         jne     short FEMLockedh
  1302.         
  1303.         ; Mark the block as FREE and cancel any locks.
  1304.         mov        [si].Flags,FREEFLAG
  1305.         mov        [si].cLock,0
  1306.         
  1307.         ; Is an adjacent block also free?
  1308. FEMScanIt:  mov        bx,[si].Base        ; BX = Bottom of block
  1309.         mov        ax,bx
  1310.         add        ax,[si].Len            ; AX = Top of block
  1311.         
  1312.         ; Search for an adjacent FREE block.
  1313.         mov        di,[KiddValley]        ; DI = Handle being scanned
  1314.         
  1315.         mov     cx,cHandles         ; Loop through the handle table
  1316. FEMLoopTop: cmp        [di].Flags,FREEFLAG        ; Is this block free?
  1317.         jne     short FEMNexth        ; No, continue
  1318.  
  1319.         ; Is this block just above the one we are freeing?
  1320.         mov        dx,[di].Base
  1321.         cmp     dx,ax
  1322.         je        short FEMBlockAbove     ; Yes, coaless upwards
  1323.  
  1324.         ; Is it just below?
  1325.         add        dx,[di].Len
  1326.         cmp     dx,bx
  1327.         je        short FEMBlockBelow     ; Yes, coaless downwards
  1328.         
  1329. FEMNexth:   add        di,SIZE Handle
  1330.         loop    FEMLoopTop
  1331.  
  1332.         ; No adjacent blocks to coaless.
  1333.         mov     ax,1            ; Return success
  1334.         xor        bl,bl
  1335.         ret
  1336.  
  1337.         ; Exchange the pointer to the "upper" and "lower" blocks.
  1338. FEMBlockBelow:
  1339.         xchg    si,di
  1340.  
  1341.         ; Move the free block above into the current handle.
  1342. FEMBlockAbove:
  1343.         mov        dx,[si].Len
  1344.         add     dx,[di].Len         ; Combine the lengths
  1345.         mov        [si].Len,dx
  1346.         mov     [di].Flags,UNUSEDFLAG   ; Mark old block's handle as UNUSED
  1347.         jmp        short FEMScanIt        ; Rescan the list
  1348.  
  1349. FEMBadh:    mov        bl,ERR_INVALIDHANDLE
  1350.         jmp        short FEMErrExit
  1351.         
  1352. FEMLockedh: mov        bl,ERR_EMBLOCKED
  1353. FEMErrExit: xor     ax,ax            ; Return failure
  1354.         ret
  1355.         
  1356. FreeExtMemory endp          
  1357.  
  1358.  
  1359. ;*--------------------------------------------------------------------------*
  1360. ;*                                        *
  1361. ;*  LockExtMemory -                        FUNCTION 0Ch    *
  1362. ;*                                        *
  1363. ;*    Locks a block of extended memory                    *
  1364. ;*                                        *
  1365. ;*  ARGS:   DX = 16-bit handle to the extended memory block            *
  1366. ;*  RETS:   AX = 1 of successful, 0 otherwise.    BL = Error code            *
  1367. ;*        DX:BX = 32-bit linear address of the base of the memory block   *
  1368. ;*  REGS:   AX, BX, DX and Flags clobbered                    *
  1369. ;*                                        *
  1370. ;*  INTERNALLY NON-REENTRANT                            *
  1371. ;*                                        *
  1372. ;*--------------------------------------------------------------------------*
  1373.  
  1374. LockExtMemory proc near
  1375.  
  1376.         cli                 ; This is a non-reentrant function
  1377.         
  1378.         ; Is the handle valid?
  1379.         call    ValidateHandle
  1380.         jnc     short LEMBadh
  1381.         mov     bx,dx            ; Move the handle into BX
  1382.  
  1383.         ; Are we at some preposterously large limit?
  1384.         cmp        [bx.cLock],0FFh
  1385.         je        short LEMOverflow
  1386.  
  1387.         ; Lock the block.
  1388.         inc        [bx.cLock]
  1389.         
  1390.         ; Return the 32-bit address of its base.
  1391.         mov        dx,[bx.Base]
  1392.         mov        bx,dx
  1393.         shr        dx,6
  1394.         shl        bx,10
  1395.  
  1396.         ; Return success.
  1397.         mov        ax,1
  1398.         ret
  1399.         
  1400. LEMBadh:    mov        bl,ERR_INVALIDHANDLE
  1401.         jmp        short LEMErrExit
  1402.  
  1403. LEMOverflow:mov        bl,ERR_LOCKOVERFLOW
  1404. LEMErrExit: xor     ax,ax            ; Return failure
  1405.         mov        dx,ax
  1406.         ret 
  1407.         
  1408. LockExtMemory endp
  1409.  
  1410.  
  1411. ;*--------------------------------------------------------------------------*
  1412. ;*                                        *
  1413. ;*  UnlockExtMemory -                        FUNCTION 0Dh    *
  1414. ;*                                        *
  1415. ;*    Unlocks a block of extended memory                    *
  1416. ;*                                        *
  1417. ;*  ARGS:   DX = 16-bit handle to the extended memory block            *
  1418. ;*  RETS:   AX = 1 if successful, 0 otherwise.    BL = Error code            *
  1419. ;*  REGS:   AX, BX and Flags clobbered                        *
  1420. ;*                                        *
  1421. ;*  INTERNALLY NON-REENTRANT                            *
  1422. ;*                                        *
  1423. ;*--------------------------------------------------------------------------*
  1424.  
  1425. UnlockExtMemory proc near
  1426.  
  1427.         cli                ; This is a non-reentrant function
  1428.     
  1429.         ; Is the handle valid?
  1430.         call    ValidateHandle
  1431.         jnc     short UEMBadh
  1432.         mov        bx,dx        ; Move the handle into BX
  1433.  
  1434.         ; Does the handle point to a locked block?
  1435.         cmp        [bx.cLock],0
  1436.         je        short UEMUnlocked    ; No, return error
  1437.  
  1438.         ; Unlock the block.
  1439.         dec        [bx.cLock]
  1440.  
  1441.         mov     ax,1        ; Return success
  1442.         xor     bl,bl
  1443.         ret
  1444.         
  1445. UEMUnlocked:mov        bl,ERR_EMBUNLOCKED
  1446.         jmp        short UEMErrExit
  1447.  
  1448. UEMBadh:    mov        bl,ERR_INVALIDHANDLE
  1449. UEMErrExit: xor        ax,ax
  1450.         ret           
  1451.  
  1452. UnlockExtMemory endp
  1453.  
  1454.  
  1455. ;*--------------------------------------------------------------------------*
  1456. ;*                                        *
  1457. ;*  GetExtMemoryInfo -                        FUNCTION 0Eh    *
  1458. ;*                                        *
  1459. ;*    Gets other information about an extended memory block            *
  1460. ;*                                        *
  1461. ;*  ARGS:   DX = 16-bit handle to the extended memory block            *
  1462. ;*  RETS:   AX = 1 if successful, 0 otherwise.    BL = Error code            *
  1463. ;*        BH = EMB's lock count                        *
  1464. ;*        BL = Total number of unused handles in the system            *
  1465. ;*        DX = EMB's length                            *
  1466. ;*  REGS:   AX, BX, CX, DX and Flags clobbered                    *
  1467. ;*                                        *
  1468. ;*  INTERNALLY NON-REENTRANT                            *
  1469. ;*                                        *
  1470. ;*--------------------------------------------------------------------------*
  1471.  
  1472. GetExtMemoryInfo proc    near
  1473.  
  1474.         cli                 ; This is a non-reentrant function
  1475.         
  1476.         ; Is the handle valid?
  1477.         call    ValidateHandle
  1478.         jnc     short GEMBadh
  1479.         mov     si,dx            ; Move the handle into SI
  1480.  
  1481.         ; Count the number of handles which are not currently being used.
  1482.         xor     al,al
  1483.         mov     bx,[KiddValley]
  1484.         mov     cx,[cHandles]        ; Loop through the handle table
  1485. GEMLoop:    cmp     [bx.Flags],USEDFLAG     ; Is this handle in use?
  1486.         je        short GEMNexth          ; Yes, continue
  1487.         inc     al                ; No, increment the count
  1488. GEMNexth:   add     bx,SIZE Handle
  1489.         loop    GEMLoop
  1490.  
  1491.         ; Setup the return.
  1492.         mov     dx,[si.Len]         ; Length in DX
  1493.         mov     bh,[si.cLock]        ; Lock count in BH
  1494.         mov     bl,al
  1495.         mov        ax,1
  1496.         ret
  1497.         
  1498. GEMBadh:    mov        bl,ERR_INVALIDHANDLE
  1499.         xor        ax,ax
  1500.         ret
  1501.  
  1502. GetExtMemoryInfo endp
  1503.         
  1504.  
  1505. ;*--------------------------------------------------------------------------*
  1506. ;*                                        *
  1507. ;*  ReallocExtMemory -                        FUNCTION 0Fh    *
  1508. ;*                                        *
  1509. ;*    Reallocates a block of extended memory                    *
  1510. ;*                                        *
  1511. ;*  ARGS:   DX = 16-bit handle to the extended memory block            *
  1512. ;*  RETS:   AX = 1 if successful, 0 otherwise.    BL = Error code            *
  1513. ;*  REGS:                                    *
  1514. ;*                                        *
  1515. ;*  INTERNALLY NON-REENTRANT                            *
  1516. ;*                                        *
  1517. ;*--------------------------------------------------------------------------*
  1518.  
  1519. ; FUNCTION NOT YET IMPLEMENTED
  1520.  
  1521.  
  1522. ;*--------------------------------------------------------------------------*
  1523. ;*                                        *
  1524. ;*  NOTE: RequestUMB and ReleaseUMB will not be implemented by HIMEM.        *
  1525. ;*                                        *
  1526. ;*--------------------------------------------------------------------------*
  1527.  
  1528.  
  1529. ;*--------------------------------------------------------------------------*
  1530. ;*                                        *
  1531. ;*  MoveExtMemory -                        FUNCTION 0Bh    *
  1532. ;*                                        *
  1533. ;*    Copys a block of memory from anywhere to anywhere            *
  1534. ;*                                        *
  1535. ;*  ARGS:   ES:SI = Pointer to an Extended Memory Block Move Structure        *
  1536. ;*        (NOTE: Originally passed in as DS:SI)                *
  1537. ;*  RETS:   AX = 1 of successful, 0 otherwise.    BL = Error code.        *
  1538. ;*  REGS:   Everybody clobbered                            *
  1539. ;*                                        *
  1540. ;*  INTERNALLY REENTRANT (believe it or not)                    *
  1541. ;*                                        *
  1542. ;*--------------------------------------------------------------------------*
  1543.  
  1544. EVEN                ; Must be word aligned.
  1545.  
  1546. MoveBlock:
  1547.  
  1548. MEM3_Data    label    byte    ; Start of MoveBlock data
  1549. MoveBlock286:
  1550.  
  1551. include xm286.asm
  1552.  
  1553.  
  1554. ;*--------------------------------------------------------------------------*
  1555.  
  1556. MoveBlock386:
  1557.  
  1558. include xm386.asm
  1559.  
  1560. EndMoveBlock386:
  1561.  
  1562.  
  1563. ;****************************************************************************
  1564. ;*                                        *
  1565. ;* A20 Handler Section:                             *
  1566. ;*                                        *
  1567. ;* The Init code copies the proper A20 Handler in place just below the        *
  1568. ;*   proper MoveBlock routine.                            *
  1569. ;*                                        *
  1570. ;* NOTE: A20 HANDLERS MUST ONLY HAVE RELATIVE JUMPS!  HOWEVER ANY CALLS TO  *
  1571. ;*     FUNCTIONS OUTSIDE OF THE HANDLER MUST BE NON-RELATIVE!     The best   *
  1572. ;*     method is to call thru a variable such as ControlJumpTable[n].        *
  1573. ;*                                        *
  1574. ;****************************************************************************
  1575.  
  1576. ;*--------------------------------------------------------------------------*
  1577. ;*                                        *
  1578. ;*  AT_A20Handler -                        HARDWARE DEP.   *
  1579. ;*                                        *
  1580. ;*    Enable/Disable the A20 line on non-PS/2 machines            *
  1581. ;*                                        *
  1582. ;*  ARGS:   AX = 0 for Disable, 1 for Enable                    *
  1583. ;*  RETS:   AX = 1 for success, 0 otherwise                    *
  1584. ;*  REGS:   AX, CX and Flags clobbered                        *
  1585. ;*                                        *
  1586. ;*--------------------------------------------------------------------------*
  1587.  
  1588. AT_A20Handler proc   near
  1589.  
  1590.         or        ax,ax
  1591.         jz        short AAHDisable
  1592.  
  1593. AAHEnable:  call    Sync8042    ; Make sure the Keyboard Controller is Ready
  1594.         jnz     short AAHErr
  1595.  
  1596.         mov        al,0D1h    ; Send D1h
  1597.         out        64h,al
  1598.         call    Sync8042
  1599.         jnz     short AAHErr
  1600.  
  1601.         mov        al,0DFh    ; Send DFh
  1602.         out        60h,al
  1603.         call    Sync8042
  1604.         jnz     short AAHErr
  1605.  
  1606.         ; Wait for the A20 line to settle down (up to 20usecs)
  1607.         mov        al,0FFh    ; Send FFh (Pulse Output Port NULL)
  1608.         out        64h,al
  1609.         call    Sync8042
  1610.         jnz     short AAHErr
  1611.         jmp        short AAHExit
  1612.  
  1613. AAHDisable: call    Sync8042    ; Make sure the Keyboard Controller is Ready
  1614.         jnz     short AAHErr
  1615.  
  1616.         mov        al,0D1h    ; Send D1h
  1617.         out        64h,al
  1618.         call    Sync8042
  1619.         jnz     short AAHErr
  1620.  
  1621.         mov        al,0DDh    ; Send DDh
  1622.         out        60h,al
  1623.         call    Sync8042
  1624.         jnz     short AAHErr
  1625.  
  1626.         ; Wait for the A20 line to settle down (up to 20usecs)
  1627.         mov        al,0FFh    ; Send FFh (Pulse Output Port NULL)
  1628.         out        64h,al
  1629.         call    Sync8042
  1630.         
  1631. AAHExit:    mov        ax,1
  1632.         ret
  1633.         
  1634. AAHErr:        xor        ax,ax
  1635.         ret
  1636.         
  1637. AT_A20Handler endp
  1638.  
  1639.  
  1640. ;*--------------------------------------------------------------------------*
  1641.  
  1642. Sync8042    proc    near
  1643.  
  1644.         xor        cx,cx
  1645. S8InSync:   in        al,64h
  1646.         and        al,2
  1647.         loopnz  S8InSync
  1648.         ret
  1649.  
  1650. Sync8042    endp
  1651.  
  1652. EndAT_A20Handler:
  1653.  
  1654.  
  1655. ;*--------------------------------------------------------------------------*
  1656. ;*                                        *
  1657. ;*  PS2_A20Handler -                        HARDWARE DEP.   *
  1658. ;*                                        *
  1659. ;*    Enable/Disable the A20 line on PS/2 machines                *
  1660. ;*                                        *
  1661. ;*  ARGS:   AX = 0 for Disable, 1 for Enable                    *
  1662. ;*  RETS:   AX = 1 for success, 0 otherwise                    *
  1663. ;*  REGS:   AX, CX and Flags clobbered                        *
  1664. ;*                                        *
  1665. ;*--------------------------------------------------------------------------*
  1666.  
  1667. PS2_PORTA   equ        0092h
  1668. PS2_A20BIT  equ        00000010b
  1669.  
  1670. PS2_A20Handler proc   near
  1671.  
  1672.         or        ax,ax
  1673.         jz        short PAHDisable
  1674.  
  1675. PAHEnable:  in        al,PS2_PORTA    ; Get the current A20 state
  1676.         test    al,PS2_A20BIT   ; Is A20 already on?
  1677.         jnz     short PAHErr
  1678.  
  1679.         or        al,PS2_A20BIT   ; Turn on the A20 line
  1680.         out        PS2_PORTA,al
  1681.  
  1682.         xor        cx,cx        ; Make sure we loop for awhile
  1683. PAHIsItOn:  in        al,PS2_PORTA    ; Loop until the A20 line comes on
  1684.         test    al,PS2_A20BIT
  1685.         loopz   PAHIsItOn
  1686.         jz        short PAHErr    ; Unable to turn on the A20 line
  1687.         jmp        short PAHExit
  1688.  
  1689. PAHDisable: in        al,PS2_PORTA    ; Get the current A20 state
  1690.         and        al,NOT PS2_A20BIT    ; Turn off the A20 line
  1691.         out        PS2_PORTA,al
  1692.  
  1693.         xor        cx,cx        ; Make sure we loop for awhile
  1694. PAHIsItOff: in        al,PS2_PORTA    ; Loop until the A20 line goes off
  1695.         test    al,PS2_A20BIT
  1696.         loopnz  PAHIsItOff
  1697.         jnz     short PAHErr    ; Unable to turn off the A20 line
  1698.  
  1699. PAHExit:    mov        ax,1
  1700.         ret
  1701.         
  1702. PAHErr:        xor        ax,ax
  1703.         ret           
  1704.  
  1705. PS2_A20Handler endp
  1706.  
  1707. EndPS2_A20Handler:
  1708.  
  1709.  
  1710. ;*--------------------------------------------------------------------------*
  1711. ;*                                        *
  1712. ;*  $6300Plus_A20Handler -                    HARDWARE DEP.   *
  1713. ;*                                        *
  1714. ;*     Enable/Disable address lines A20-A23 on AT&T 6300 Plus            *
  1715. ;*                                        *
  1716. ;*  ARGS:   AX = 0 for Disable, 1 for Enable                    *
  1717. ;*  RETS:   AX = 1 for success, 0 otherwise                    *
  1718. ;*  REGS:   AX, BX, and Flags clobbered                        *
  1719. ;*                                        *
  1720. ;*  Note:   Don't want to do two back to back disables on PLUS,            *
  1721. ;*        so we call IsA20On to see if it is necessary.            *
  1722. ;*  Warning:  The calcuation of the ReturnBack label depends on the        *
  1723. ;*          expectation that this routine is being moved at init time.    *
  1724. ;*                                        *
  1725. ;*--------------------------------------------------------------------------*
  1726.  
  1727. PLUS_PORT   equ        03F20h
  1728. PLUS_STATUS equ     03FA0h
  1729. PLUS_SET    equ     10000000b    ; Turn on A20-A23
  1730. PLUS_RESET  equ     00010000b    ; Turn off A20-A23 and point to our routine
  1731.  
  1732. $6300PLUS_A20Handler proc   near
  1733.             mov     bx,ax
  1734.             push    dx
  1735.             mov     dx,PLUS_STATUS
  1736.             in      al,dx
  1737.             pop     dx
  1738.             and     ax,1
  1739.             cmp     ax,bx
  1740.             jne     short $6AHEnable
  1741.         mov     ax,1
  1742.             ret                             ; No, just return
  1743.  
  1744. $6AHEnable: 
  1745.             pushf
  1746.             sti
  1747.             mov     al,PLUS_SET
  1748.             or      bx,bx                   ; Zero if disable
  1749.             jnz     short $6AHNext
  1750.             mov     al,PLUS_RESET
  1751.  
  1752. $6AHNext:   push    dx                      ; Set/reset the port
  1753.             mov     dx,PLUS_PORT
  1754.             out     dx,al
  1755.             pop     dx
  1756.             or      bx,bx
  1757.             jnz     short $6AHNext1
  1758.             call    $6300Reset              ; Reset the processor
  1759. $6AHNext1:
  1760.             popff
  1761.             mov ax,1
  1762.             ret
  1763.  
  1764. $6300Plus_A20Handler endp
  1765.  
  1766.  
  1767. ;*--------------------------------------------------------------------------*
  1768. ;*                                        *
  1769. ;* $6300Reset -                           HARDWARE DEP.    *
  1770. ;*                                        *
  1771. ;* Reset the 80286 in order to turn off the address lines on the 6300 PLUS. *
  1772. ;* This is the only way to do this on the current hardware.            *
  1773. ;* The processor itself is reset by reading or writing port 03F00h.        *
  1774. ;*                                        *
  1775. ;*  Uses flags.                                    *
  1776. ;*                                        *
  1777. ;*--------------------------------------------------------------------------*
  1778.  
  1779. $6300Reset  proc    near
  1780.  
  1781.         pusha                ; Save world
  1782.         push    ds                ; Save segments
  1783.         push    es
  1784.         mov        ax,BiosSeg            ; Point to the BIOS segment
  1785.         mov        ds,ax            ; ds -> 40h
  1786.  
  1787.         ; Setup the reset return address.
  1788. assume ds:nothing
  1789.         push    word ptr ds:[RealLoc1]  ; Save what might have been here
  1790.         push    word ptr ds:[RealLoc1+2]
  1791.  
  1792.             ; Load our return address, remembering that we will be relocated
  1793.             ;   at init time.
  1794.             mov     word ptr ds:[RealLoc1+2],cs
  1795.             mov     ax,cs:[A20Handler]
  1796.             add     ax,offset ReturnBack-offset $6300Plus_A20Handler
  1797.             mov     word ptr ds:[RealLoc1],ax 
  1798.             mov     cs:[OldStackSeg],ss     ; Save the stack segment, too
  1799.  
  1800.         ; Reset the processor - turning off A20 in the process.
  1801.         mov        dx,03F00h
  1802.         in        ax,dx
  1803.  
  1804.         ; We shouldn't get here.  Halt the machine if we do.
  1805.         nop
  1806.         nop
  1807.         nop
  1808.         nop
  1809.         cli
  1810.         hlt
  1811.  
  1812. ReturnBack: mov        ss,cs:[OldStackSeg]        ; Start the recovery
  1813.         pop        word ptr ds:[RealLoc1+2]    ; ROM code has set ds->40h
  1814.         pop        word ptr ds:[RealLoc1]
  1815.         pop        es
  1816.         pop        ds
  1817.  
  1818. assume ds:code
  1819.             xor     al,al
  1820.             mov     dx,PLUS_PORT
  1821.             out     dx,al
  1822.             popa
  1823.             ret
  1824.  
  1825. $6300Reset endp
  1826.  
  1827. End6300Plus_Handler:
  1828.  
  1829.  
  1830. ;*--------------------------------------------------------------------------*
  1831. ;*                                        *
  1832. ;*  HP_A20Handler -                        HARDWARE DEP.   *
  1833. ;*                                        *
  1834. ;*    Enable/Disable the A20 line on HP Vectra machines            *
  1835. ;*                                        *
  1836. ;*  ARGS:   AX = 0 for Disable, 1 for Enable                    *
  1837. ;*  RETS:   AX = 1 for success, 0 otherwise                    *
  1838. ;*  REGS:   AX, CX and Flags clobbered                        *
  1839. ;*                                        *
  1840. ;*--------------------------------------------------------------------------*
  1841.  
  1842. HP_A20Handler proc   near
  1843.  
  1844.         or        ax,ax
  1845.         jz        short HAHDisable
  1846.  
  1847. HAHEnable:  call    HPSync8042    ; Make sure the Keyboard Controller is ready
  1848.         jnz     short HAHErr
  1849.  
  1850.         mov        al,0DFh    ; Send DFh
  1851.         out        64h,al
  1852.         call    HPSync8042
  1853.         jnz     short HAHErr
  1854.  
  1855.         mov        al,0DFh    ; Send second DFh
  1856.         out        64h,al
  1857.         call    HPSync8042
  1858.         jnz     short HAHErr
  1859.         jmp        short HAHExit
  1860.  
  1861. HAHDisable: call    HPSync8042      ; Make sure the Keyboard Controller is Ready
  1862.         jnz     short HAHErr
  1863.  
  1864.         mov        al,0DDh    ; Send DDh
  1865.         out        64h,al
  1866.         call    HPSync8042
  1867.         jnz     short HAHErr
  1868.  
  1869.         mov        al,0DDh    ; Send second DDh
  1870.         out        64h,al
  1871.         call    HPSync8042
  1872.         jnz     short HAHErr
  1873.  
  1874. HAHExit:    mov        ax,1
  1875.         ret
  1876.  
  1877. HAHErr:        xor        ax,ax
  1878.         ret
  1879.         
  1880. HP_A20Handler endp
  1881.  
  1882.  
  1883. ;*--------------------------------------------------------------------------*
  1884.  
  1885. HPSync8042  proc    near
  1886.  
  1887.         xor        cx,cx
  1888. H8InSync:   in        al,64h
  1889.         and        al,2
  1890.         loopnz  H8InSync
  1891.         ret
  1892.  
  1893. HPSync8042  endp
  1894.  
  1895. EndHP_A20Handler:
  1896.  
  1897.  
  1898. ;*--------------------------------------------------------------------------*
  1899. ;*                                        *
  1900. ;*  Extended Memory Handle Table -                        *
  1901. ;*                                        *
  1902. ;*--------------------------------------------------------------------------*
  1903.  
  1904. ; Actually, the handle table will be located just after the end of whichever
  1905. ; A20 Handler is installed and will overwrite the others.  In large cases
  1906. ; however, it could extend beyond all of these guys and crunch the Init code.
  1907. ; Hence this buffer.  If the driver ever gets over 64K (heaven forbid) this
  1908. ; scheme should be reworked.
  1909.  
  1910. ; Guarantee space for all handles.  Kinda overkill but any extra will be 
  1911. ; discarded with the Init code.
  1912.  
  1913. HandleFiller        dw        MAXHANDLES * SIZE Handle DUP(?)
  1914.  
  1915.  
  1916. ;****************************************************************************
  1917. ;*                                        *
  1918. ;*  NOTE: Code below here will be discarded after driver initialization.    *
  1919. ;*                                        *
  1920. ;****************************************************************************
  1921.  
  1922. ;*--------------------------------------------------------------------------*
  1923. ;*                                        *
  1924. ;*  InitDriver -                                *
  1925. ;*                                        *
  1926. ;*    Called when driver is Initialized.                    *
  1927. ;*                                        *
  1928. ;*  ARGS:   ES:DI = Address of the Request Header                *
  1929. ;*  RETS:   AX = 0, pHdr.Address = Bottom of resident driver code        *
  1930. ;*  REGS:   AX, CX and Flags are clobbered                    *
  1931. ;*                                        *
  1932. ;*--------------------------------------------------------------------------*
  1933.  
  1934. InitLine    dw        MoveBlock        ; The line which defines what will be dis-
  1935.                     ;    carded after the driver is initialized
  1936. InitDriver  proc    near
  1937.  
  1938.         ; Display the sign on message.
  1939.         mov        ah,9h
  1940.         mov        dx,offset SignOnMsg
  1941.         int        21h
  1942.  
  1943.         ; Is this DOS 3.00 or higher?
  1944.         mov        ah,30h
  1945.         int        21h            ; Get DOS versions number
  1946.         cmp        al,3
  1947.         jae     short IDCheckXMS
  1948.         
  1949.         mov        dx,offset BadDOSMsg
  1950.         jmp     short IDFlushMe2
  1951.             
  1952.         ; Is another XMS driver already installed?
  1953. IDCheckXMS: mov     ax,4300h
  1954.         int        2Fh
  1955.         cmp        al,80h        ; Is INT 2F hooked?
  1956.         jne     short IDNotInYet
  1957.         mov        dx,offset NowInMsg
  1958.         jmp     short IDFlushMe2
  1959.  
  1960.         ; What kind of processor are we on?
  1961. IDNotInYet: call    MachineCheck
  1962.         cmp        ax,1        ; Is it an 8086/8088?
  1963.         jne     short IDProcOK
  1964.         mov        dx,offset On8086Msg
  1965.         jmp     short IDFlushMe
  1966.  
  1967.         ; Is there any Compaq BIM?
  1968. IDProcOK:
  1969.         call    GetBIMMemory
  1970.         or        ax,ax
  1971.         jz        short IDNoBIM
  1972.  
  1973.         ; How much extended memory is installed?
  1974.         call    GetInt15Memory
  1975.         cmp     ax,64        ; Is there >= 64K of extended?
  1976.         jb        short IDNoHMA    ; Nope - No HMA
  1977.         jmp     short IDHMAOK    ; Yup - continue
  1978.  
  1979.         ; How much extended memory is installed?
  1980. IDNoBIM:    call    GetInt15Memory
  1981.         cmp     ax,64        ; Is there >= 64K of extended?
  1982.         jae     short IDHMAOK    ; Yup - continue
  1983.  
  1984.         or        ax,ax        ; Is there any extended?
  1985.         jnz     short IDNoHMA    ; Yup - No HMA
  1986.  
  1987.         ; We can't find any memory to manage.
  1988.         mov        dx,offset NoExtMemMsg
  1989. IDFlushMe2: jmp     short IDFlushMe
  1990.         
  1991.         ; There isn't enough for the HMA, but there is some extended
  1992.         ; memory which we can manage.
  1993. IDNoHMA:    mov     dx,offset NoHMAMsg
  1994.         mov        ah,9h
  1995.         int        21h
  1996.         jmp     short IDFinalInit
  1997.  
  1998. IDHMAOK:    mov     [fHMAMayExist],1
  1999.  
  2000.         ; Install the proper MoveBlock function.
  2001. IDFinalInit:call    InstallMoveBlock
  2002.  
  2003.         ; Install the proper A20 handler.
  2004.         call    InstallA20
  2005.         
  2006.         ; Was A20 on already?
  2007.         call    IsA20On
  2008.         xor        ax,1
  2009.         mov        [fCanChangeA20],al    ; Yes, don't ever disable it
  2010.         cmp     al,0
  2011.         jne     short IDDiddler
  2012.         
  2013.         ; Display the "A20 Already On" message.
  2014.         mov        dx,offset A20OnMsg
  2015.         mov     ah,9h        ; CHANGED - 8/9/88
  2016.         int        21h
  2017.         
  2018.         ; Can we successfully diddle A20?    CHANGED - 8/9/88
  2019. IDDiddler:  call    LocalEnableA20    ; Try to enable A20
  2020.         or        ax,ax        ; Did we do it?
  2021.         jz        short IDBadA20    ; Nope - phoosh ourselves
  2022.  
  2023.         call    IsA20On        ; Is A20 on?
  2024.         or        ax,ax
  2025.         jz        short IDBadA20    ; Nope - phoosh ourselves
  2026.  
  2027.         call    LocalDisableA20    ; Try to disable A20
  2028.         or        ax,ax        ; Did we do it?
  2029.         jnz     short IDA20Cont    ; Yup - continue
  2030.  
  2031.         cmp     [fCanChangeA20],1    ; Has A20 been permenantly enabled?
  2032.         je        short IDGetParms    ; Yup - continue
  2033.         jmp     short IDBadA20    ; Nope - phoosh ourselves
  2034.         
  2035. IDA20Cont:  call    IsA20On        ; Is A20 off?
  2036.         or        ax,ax
  2037.         jz        short IDGetParms    ; Yup - continue
  2038.  
  2039.         ; A20 ain't doing it.
  2040. IDBadA20:   mov        dx,offset BadA20Msg
  2041.  
  2042.         ; Display the message in DX followed by the "Flush" message.
  2043. IDFlushMe:  mov        ah,9h
  2044.         int        21h
  2045.         mov        dx,offset FlushMsg
  2046.         mov        ah,9h
  2047.         int        21h
  2048.         
  2049.         ; Discard the entire driver.
  2050.         xor        ax,ax
  2051.         mov        [InitLine],ax
  2052.         les        di,[pReqHdr]
  2053.         mov        es:[di.Units],al
  2054.         jmp        short IDReturn
  2055.         
  2056.         ; Process the command line parameters.
  2057. IDGetParms: call    GetParms
  2058.         
  2059.         ; Initialize the Handle Table.
  2060.         call    InitHandles
  2061.  
  2062.         ; Display the success messages.
  2063.         cmp        [fHMAMayExist],0
  2064.         je        short IDIgnition
  2065.         mov        dx,offset HMAOKMsg
  2066.         mov        ah,9h
  2067.         int        21h
  2068.  
  2069.         ; "Turn On" the driver.
  2070. IDIgnition: call    HookInt2F
  2071.  
  2072.         ; Discard the initialization code.
  2073. IDReturn:   les        di,[pReqHdr]
  2074.         mov        ax,[InitLine]
  2075.         mov        word ptr es:[di.Address][0],ax
  2076.         mov        word ptr es:[di.Address][2],cs
  2077.  
  2078.         ; Return success.
  2079.         xor        ax,ax
  2080.         ret
  2081.  
  2082. InitDriver  endp
  2083.  
  2084.         
  2085. ;*--------------------------------------------------------------------------*
  2086. ;*                                        *
  2087. ;*  HookInt2F -                                    *
  2088. ;*                                        *
  2089. ;*    Insert the INT 2F hook                            *
  2090. ;*                                        *
  2091. ;*  ARGS:   None                                *
  2092. ;*  RETS:   None                                *
  2093. ;*  REGS:   AX, SI, ES and Flags are clobbered                    *
  2094. ;*                                        *
  2095. ;*  EXTERNALLY NON-REENTRANT                            *
  2096. ;*    Interrupts must be disabled before calling this function.        *
  2097. ;*                                        *
  2098. ;*--------------------------------------------------------------------------*
  2099.  
  2100. HookInt2F   proc    near
  2101.  
  2102.         ; Save the current INT 2F vector
  2103.         cli
  2104.         xor        ax,ax
  2105.         mov        es,ax
  2106.         mov        si,2Fh * 4            ; ES:SI = Address of 2F vector
  2107.  
  2108.         ; Exchange the old vector with the new one
  2109.         mov        ax,offset Int2FHandler
  2110.         xchg    ax,es:[si][0]
  2111.         mov        word ptr [PrevInt2F][0],ax
  2112.         mov        ax,cs
  2113.         xchg    ax,es:[si][2]
  2114.         mov        word ptr [PrevInt2F][2],ax
  2115.         sti
  2116.         ret
  2117.  
  2118. HookInt2F   endp
  2119.  
  2120.  
  2121. ;*--------------------------------------------------------------------------*
  2122. ;*                                        *
  2123. ;*  MachineCheck -                                *
  2124. ;*                                        *
  2125. ;*    Determines the CPU type.                        *
  2126. ;*                                        *
  2127. ;*  ARGS:   None                                *
  2128. ;*  RETS:   AX = 1 if we're on an 8086/8088 or an 80186, 0 otherwise        *
  2129. ;*  REGS:   AX and Flags are clobbered                        *
  2130. ;*                                        *
  2131. ;*--------------------------------------------------------------------------*
  2132.  
  2133. ; NOTE: This is the "official" Intel method for determining CPU type.
  2134.  
  2135. MachineCheck proc   near
  2136.  
  2137.         xor     ax,ax        ; Move 0 into the Flags register
  2138.         push    ax
  2139.         popf
  2140.         pushf            ; Try and get it back out
  2141.         pop     ax
  2142.         and     ax,0F000h        ; If the top four bits are set...
  2143.         cmp     ax,0F000h
  2144.         je        short MC_8086    ; ...it's an 8086 machine
  2145.  
  2146.         mov     ax,0F000h        ; Move F000h into the Flags register
  2147.         push    ax
  2148.         popf
  2149.         pushf            ; Try and get it back out
  2150.         pop     ax
  2151.         and     ax,0F000h        ; If the top four bits aren't set...
  2152.         jz        short MC_80286    ; ...it's an 80286 machine
  2153.  
  2154.         ; We're on an 80386 machine
  2155.         mov     ax,3
  2156.         ret
  2157.  
  2158. MC_80286:   ; We're on an 80286 machine
  2159.         mov     ax,2
  2160.         ret
  2161.  
  2162. MC_8086:    ; We're on an 8086 machine
  2163.         mov     ax,1
  2164.         ret
  2165.         
  2166. MachineCheck endp
  2167.  
  2168.         
  2169. ;*--------------------------------------------------------------------------*
  2170. ;*                                        *
  2171. ;*  GetBIMMemory -                                *
  2172. ;*                                        *
  2173. ;*    Look for Compaq 'Built In Memory' and add it to the pool of        *
  2174. ;*  available memory                                *
  2175. ;*                                        *
  2176. ;*  ARGS:   None                                *
  2177. ;*  RETS:   AX = Amount of BIM memory found                    *
  2178. ;*  REGS:   AX, BX, CX, and Flags are clobbered                    *
  2179. ;*                                        *
  2180. ;*--------------------------------------------------------------------------*
  2181.  
  2182. ; "Built In Memory" (BIM) starts at FE00:0000h and grows downward.  It is
  2183. ; controlled by a data structure at F000:FFE0h.  Changing the data structure
  2184. ; involves un-write-protecting the ROMs (!) by flipping bit 1 of 80C00000.
  2185.  
  2186. pBIMSTRUCT  equ     0FFE0h
  2187. AVAILABLE   equ     0        ; Set to -1 if BIM isn't around
  2188. TOTALBIM    equ     2        ; Total amount of BIM in the system
  2189. AVAILBIM    equ     4        ; Amount of BIM available in paragraphs
  2190. LASTUSED    equ     6        ; Paragraph address of last (lowest) used
  2191.                 ;  paragraph of BIM
  2192.  
  2193. pCOMPAQ     label   dword
  2194.         dw        0FFE8h
  2195.         dw        0F000h
  2196.         
  2197. szCOMPAQ    db        '03COMPAQ'
  2198.  
  2199. pRAMRELOC   label   dword
  2200.         dw        00000h
  2201.         dw        080C0h
  2202.  
  2203. GDT_TYPE    struc
  2204.         dw        0,0,0,0
  2205.         dw        0,0,0,0
  2206.  
  2207. S_LIMIT     dw        1
  2208. S_BASE_LOW  dw        0
  2209. S_BASE_HI   db        0
  2210. S_RIGHTS    db        93h
  2211. S_RESERVED  dw        0
  2212.  
  2213. D_LIMIT     dw        1
  2214. D_BASE_LOW  dw        0000h
  2215. D_BASE_HI   db        0C0h
  2216. D_RIGHTS    db        93h
  2217. D_RES386    db        0
  2218. D_BASE_XHI  db        080h
  2219.  
  2220.         dw        0,0,0,0
  2221.         dw        0,0,0,0
  2222. GDT_TYPE    ends
  2223.  
  2224. BIMGDT        GDT_TYPE <>
  2225.  
  2226. BIMBuffer   dw        ?
  2227.  
  2228.  
  2229. GetBIMMemory proc near
  2230.  
  2231.         xor     ax,ax
  2232.  
  2233.         ; Are we on a Compaq 386 machine?
  2234.         push    es
  2235.  
  2236.         ; Set up the comparison.
  2237.         les     di,cs:pCOMPAQ
  2238.         mov     si,offset szCOMPAQ
  2239.         mov     cx,8
  2240.         cld
  2241.         rep     cmpsb            ; Do the comparison
  2242.  
  2243.         jne     short FCMNoMem2        ; Nope, return
  2244.  
  2245.         ; Is there a 32-bit memory board installed?
  2246.         mov     bx,pBIMSTRUCT
  2247.         mov     bx,es:[bx]            ; De-reference the pointer
  2248.         mov     dx,es:[bx+AVAILABLE]    ; -1 means no board is installed
  2249.         inc     dx
  2250.         jz        short FCMNoMem2        ; Nope, return
  2251.  
  2252.         ; How much memory is available and where does it start?
  2253.         mov     dx,es:[bx+AVAILBIM]     ; Size in paragraphs
  2254.         or        dx,dx            ; Any left?
  2255.         jz        short FCMNoMem
  2256.         mov     cx,dx            ; CX = Size in paragraphs
  2257.         mov     ax,es:[bx+LASTUSED]
  2258.         sub     ax,cx            ; AX = Starting location - F0000h
  2259.                         ;         in paragraphs
  2260.         push    es                ; Save for a rainy day...
  2261.         push    bx
  2262.         push    ax
  2263.  
  2264.         ; Change AX to the starting location in K.
  2265.         shr     ax,4
  2266.         add     ax,0F000h
  2267.         shr     ax,2
  2268.  
  2269.         ; Change CX to the size in K.
  2270.         shr     cx,6
  2271.  
  2272.         ; Store away for use by HookInt15().
  2273.         mov     [BIMBase],ax
  2274.         mov     [BIMLength],cx
  2275.  
  2276.         ; Un-WriteProtect the ROMs.
  2277.         mov     si,offset BIMGDT            ; Set up the BlockMove GDT
  2278.         mov     ax,cs
  2279.         mov     es,ax
  2280.         mov     cx,16
  2281.         mul     cx
  2282.         add     ax,offset BIMBuffer
  2283.         adc     dl,0
  2284.         mov     [si.S_BASE_LOW],ax
  2285.         mov     [si.S_BASE_HI],dl
  2286.         mov     cx,1
  2287.  
  2288.         mov     word ptr [BIMBuffer],0FEFEh     ; FEh unlocks the ROMs
  2289.  
  2290.         mov     ah,87h                ; Do the BlockMove
  2291.         int     15h
  2292.         or        ah,ah                ; Was there an error?
  2293.         jz        short FCMReserve            ; Nope - continue
  2294.  
  2295.         ; Return error.
  2296.         pop     ax                    ; Clean up
  2297.         pop     bx
  2298.         pop     es
  2299.         xor     ax,ax
  2300.         mov     [BIMBase],ax
  2301.         mov     [BIMLength],ax
  2302. FCMNoMem2:  jmp     short FCMNoMem
  2303.  
  2304.         ; Change the ROM values to reserve the BIM stuff.
  2305. FCMReserve: pop     ax
  2306.         pop     bx
  2307.         pop     es
  2308.         mov     word ptr es:[bx+AVAILBIM],0      ; Reserve all remaining BIM
  2309.         mov     word ptr es:[bx+LASTUSED],ax
  2310.  
  2311.         ; Re-WriteProtect the ROMs.
  2312.         push    cs
  2313.         pop     es
  2314.         mov     si,offset BIMGDT            ; Set up the BlockMove GDT
  2315.  
  2316.         mov     word ptr [BIMBuffer],0FCFCh     ; FCh unlocks the ROMs
  2317.  
  2318.         mov     ah,87h                ; Do the BlockMove
  2319.         int     15h
  2320.  
  2321.         mov     ax,1                ; Return success
  2322.  
  2323. FCMNoMem:   pop     es
  2324.         ret
  2325.  
  2326. GetBIMMemory endp
  2327.  
  2328.  
  2329. ;*--------------------------------------------------------------------------*
  2330. ;*                                        *
  2331. ;*  GetInt15Memory -                                *
  2332. ;*                                        *
  2333. ;*    Returns the amount of memory INT 15h, Function 88h says is free        *
  2334. ;*                                        *
  2335. ;*  ARGS:   None                                *
  2336. ;*  RETS:   AX = Amount of free extended memory in K-bytes            *
  2337. ;*  REGS:   AX and Flags are clobbered                        *
  2338. ;*                                        *
  2339. ;*--------------------------------------------------------------------------*
  2340.         
  2341. GetInt15Memory proc near
  2342.  
  2343.         ; Check for 6300 Plus (to set "MemCorr").
  2344.         call    Is6300Plus
  2345.  
  2346.         ; Get the amount of extended memory Int 15h says is around.
  2347.         mov        ah,88h
  2348.         clc
  2349.         int        15h            ; Is Function 88h around?
  2350.         jnc     short GIM100
  2351.         xor        ax,ax        ; No, return 0
  2352.         ret
  2353.         
  2354. GIM100:        sub        ax,[MemCorr]    ; Compensate for 6300 Plus machines
  2355.         ret
  2356.  
  2357. GetInt15Memory endp               
  2358.         
  2359.         
  2360. ;*--------------------------------------------------------------------------*
  2361. ;*                                        *
  2362. ;*  InstallMoveBlock -                        HARDWARE DEP.   *
  2363. ;*                                        *
  2364. ;*    Attempt to install the proper MoveBlock function.            *
  2365. ;*                                        *
  2366. ;*  ARGS:   None                                *
  2367. ;*  RETS:   None                                *
  2368. ;*  REGS:   AX, CX, DI, SI, ES and Flags are clobbered                *
  2369. ;*                                        *
  2370. ;*--------------------------------------------------------------------------*
  2371.  
  2372. InstallMoveBlock proc near
  2373.  
  2374.         ; Are we on a 386 machine?
  2375.         call    MachineCheck
  2376.         cmp     ax,3
  2377.         je        short IMBOn386        ; Yes, install the 386 routine
  2378.  
  2379.         ; Install the 286 MoveBlock routine.
  2380.         mov     [InitLine],offset EndMoveBlock286
  2381.         call    InitMoveExtended286
  2382.         ret
  2383.  
  2384.         ; Install the 386 MoveBlock routine.
  2385. IMBOn386:   mov     si,offset MoveBlock386
  2386.         mov     cx,(offset EndMoveBlock386 - offset MoveBlock386)
  2387.  
  2388.         ; REP MOV the routine into position.
  2389.         cld
  2390.         push    cs
  2391.         pop        es
  2392.         mov     di,offset MoveBlock
  2393.         add     [InitLine],cx
  2394.         rep movsb
  2395.         call    InitMoveBlock386
  2396.         ret
  2397.  
  2398. InstallMoveBlock endp
  2399.  
  2400.  
  2401. ;*--------------------------------------------------------------------------*
  2402. ;*                                        *
  2403. ;*  InitMoveBlock386 -                        HARDWARE DEP.   *
  2404. ;*                                        *
  2405. ;*    Initializes the 386 MoveBlock routine                    *
  2406. ;*                                        *
  2407. ;*  ARGS:   None                                *
  2408. ;*  RETS:   None                                *
  2409. ;*  REGS:   AX, CX, DX and Flags are clobbered                    *
  2410. ;*                                        *
  2411. ;*--------------------------------------------------------------------------*
  2412.  
  2413. InitMoveBlock386 proc near
  2414.  
  2415.         mov     ax,cs            ; dx has CS of codeg
  2416.         mov     [patch3],ax         ; Patch code
  2417.         mov     cx,16
  2418.         mul     cx
  2419.         mov     [descCS].LO_apDesc386,ax    ; Set up selector for our CS
  2420.         mov     [descCS].MID_apDesc386,dl
  2421.         add     ax,offset code:OurGDT    ; Calculate Base of GDT
  2422.         adc     dx,0
  2423.         mov     [GDTPtr.LO_apBaseGdt],ax
  2424.         mov     [GDTPtr.HI_apBaseGdt],dx
  2425.         mov     ax,offset code:MoveExtended386+MEM3_Offset
  2426.         mov     ControlJumpTable[0Bh*2],ax
  2427.         ret
  2428.  
  2429. InitMoveBlock386 endp
  2430.  
  2431.  
  2432. ;*--------------------------------------------------------------------------*
  2433. ;*                                        *
  2434. ;*  InstallA20 -                        HARDWARE DEP.   *
  2435. ;*                                        *
  2436. ;*    Attempt to install the proper A20 Handler                *
  2437. ;*                                        *
  2438. ;*  ARGS:   None                                *
  2439. ;*  RETS:   None                                *
  2440. ;*  REGS:   AX, CX, DI, SI, ES and Flags are clobbered                *
  2441. ;*                                        *
  2442. ;*--------------------------------------------------------------------------*
  2443.  
  2444. InstallA20  proc near
  2445.         
  2446.         ; Are we on a 6300 Plus?
  2447.         call    Is6300Plus
  2448.         or        ax,ax
  2449.         jz        short IAChkPS2
  2450.  
  2451.         ; Yes, relocate 6300 Plus A20 handler.
  2452.         mov        si,offset $6300PLUS_A20Handler
  2453.         mov        cx,(offset End6300PLUS_Handler - offset $6300PLUS_A20Handler)
  2454.         jmp        short IAMoveIt
  2455.  
  2456.         ; Are we on a PS/2?
  2457. IAChkPS2:   call    IsPS2Machine
  2458.         cmp        ax,1
  2459.         jne     short IACheckHP
  2460.  
  2461.         ; Yes, relocate the PS/2 A20 handler.
  2462.         mov        si,offset PS2_A20Handler
  2463.         mov        cx,(offset EndPS2_A20Handler - offset PS2_A20Handler)
  2464.         jmp        short IAMoveIt
  2465.  
  2466.         ; Are we on a HP Vectra?
  2467. IACheckHP:  call    IsHPMachine
  2468.         cmp        ax,1
  2469.         jne     short IAOnAT
  2470.  
  2471.         ; Yes, relocate the HP A20 handler.
  2472.         mov        si,offset HP_A20Handler
  2473.         mov     cx,(offset EndHP_A20Handler - offset HP_A20Handler)
  2474.         jmp     short IAMoveIt
  2475.  
  2476. IAOnAT:     mov     si,offset AT_A20Handler
  2477.         mov     cx,(offset EndAT_A20Handler - offset AT_A20Handler)
  2478.  
  2479.         ; REP MOV the proper handler into position.
  2480. IAMoveIt:   cld
  2481.         push    cs
  2482.         pop        es
  2483.         mov     di,[InitLine]
  2484.         mov     [A20Handler],di
  2485.         add        [InitLine],cx
  2486.         rep movsb
  2487.         ret
  2488.  
  2489. InstallA20  endp
  2490.  
  2491.  
  2492. ;*--------------------------------------------------------------------------*
  2493. ;*                                        *
  2494. ;*  GetParms -                                    *
  2495. ;*                                        *
  2496. ;*    Get any parameters off of the HIMEM command line            *
  2497. ;*                                        *
  2498. ;*  ARGS:   None                                *
  2499. ;*  RETS:   None                                *
  2500. ;*  REGS:   AX, BX, CX, DX, DI, SI, ES and Flags clobbered            *
  2501. ;*                                        *
  2502. ;*  Side Effects:   cHandles and MinHMASize may be changed            *
  2503. ;*                                        *
  2504. ;*--------------------------------------------------------------------------*
  2505.  
  2506. GPRegSave   dw        ?
  2507.  
  2508. GetParms    proc    near
  2509.  
  2510.         push    ds
  2511.  
  2512.         cld
  2513.         les        di,[pReqHdr]
  2514.         lds        si,es:[di.pCmdLine]        ; DS:SI points to first char
  2515.                         ; after "DEVICE="
  2516.         ; Scan until we see a frontslash or the end of line.
  2517. GPBadParm:          
  2518. GPNextChar: lodsb
  2519.         cmp        al,'/'
  2520.         je        short GPGotOne
  2521.         cmp        al,13
  2522.         jne     short GPNextChar
  2523. GPDatsAll:  pop        ds
  2524.         ret
  2525.  
  2526.         ; Save what we found and get the number after it.
  2527. GPGotOne:   lodsb
  2528.         mov        cs:[GPRegSave],ax
  2529.         
  2530.         ; Scan past the rest of the parm for a number, EOL, or a space.
  2531. GPNeedNum:  lodsb
  2532.         cmp        al,' '
  2533.         je        short GPBadParm
  2534.         cmp        al,13
  2535.         je        short GPBadParm
  2536.         cmp        al,'0'
  2537.         jb        short GPNeedNum
  2538.         cmp        al,'9'
  2539.         ja        short GPNeedNum
  2540.         
  2541.         ; Read the number at DS:SI into DX.
  2542.         xor        dx,dx
  2543. GPNumLoop:  sub        al,'0'
  2544.         cbw
  2545.         add        dx,ax
  2546.         lodsb
  2547.         cmp        al,' '
  2548.         je        short GPNumDone
  2549.         cmp        al,13
  2550.         je        short GPNumDone
  2551.         cmp        al,'0'
  2552.         jb        short GPBadParm
  2553.         cmp        al,'9'
  2554.         ja        short GPBadParm
  2555.         shl        dx,1            ; Stupid multiply DX by 10
  2556.         mov        bx,dx
  2557.         shl        dx,1
  2558.         shl        dx,1
  2559.         add        dx,bx
  2560.         jmp        short GPNumLoop
  2561.         
  2562.         ; Which parameter are we dealing with here?
  2563. GPNumDone:  xchg    ax,cs:[GPRegSave]
  2564.         cmp        al,'H'            ; HMAMIN= parameter?
  2565.         je        short GPGotMin
  2566.         cmp        al,'N'            ; NUMHANDLES= parameter?
  2567.         jne     short GPBadParm
  2568.  
  2569.         ; Process /NUMHANDLES= parameter.
  2570. GPGotHands: cmp        dx,MAXHANDLES
  2571.         ja        short GPBadParm
  2572.  
  2573.         or        dx,dx            ; Zero?
  2574.         jz        short GPBadParm
  2575.  
  2576.         mov     cs:[cHandles],dx        ; Store it
  2577.  
  2578.         ; Print descriptive message.
  2579.         mov        dx,offset StartMsg
  2580.         call    GPPrintIt
  2581.         mov        ax,cs:[cHandles]
  2582.         call    GPPrintAX
  2583.         mov        dx,offset HandlesMsg
  2584.         call    GPPrintIt
  2585.         jmp        short GPNextParm
  2586.  
  2587.         ; Process /HMAMIN= parameter.
  2588. GPGotMin:   cmp        dx,64
  2589.         ja        short GPBadParm
  2590.  
  2591.         push    dx
  2592.         mov        cs:[MinHMASize],dx
  2593.  
  2594.         ; Print a descriptive message.
  2595.         mov        dx,offset HMAMINMsg
  2596.         call    GPPrintIt
  2597.         mov        ax,cs:[MinHMASize]
  2598.         call    GPPrintAX
  2599.         mov        dx,offset KMsg
  2600.         call    GPPrintIt
  2601.  
  2602.         pop        dx
  2603.         mov        cl,10            ; Convert from K to bytes
  2604.         shl        dx,cl
  2605.         mov        cs:[MinHMASize],dx
  2606.  
  2607.         ; Were we at the end of the line?
  2608. GPNextParm: mov        ax,cs:[GPRegSave]
  2609.         cmp        al,13
  2610.         je        short GPExit
  2611.         jmp     GPNextChar
  2612.  
  2613. GPExit:        pop        ds
  2614.         ret
  2615.         
  2616. GetParms    endp
  2617.  
  2618. ;*--------------------------------------------------------------------------*
  2619.  
  2620. GPPrintIt   proc    near
  2621.  
  2622.         push    ds                ; Save current DS
  2623.         push    cs                ; Set DS=CS
  2624.         pop        ds
  2625.         mov        ah,9h
  2626.         int        21h
  2627.         pop        ds                ; Restore DS
  2628.         ret
  2629.  
  2630. GPPrintIt   endp
  2631.  
  2632. ;*--------------------------------------------------------------------------*
  2633.  
  2634. GPPrintAX   proc    near
  2635.  
  2636.         mov        cx,10
  2637.         xor        dx,dx
  2638.         div        cx
  2639.         or        ax,ax
  2640.         jz        short GPAPrint
  2641.         push    dx
  2642.         call    GPPrintAX
  2643.         pop        dx
  2644. GPAPrint:   add        dl,'0'
  2645.         mov        ah,2h
  2646.         int        21h
  2647.         ret
  2648.  
  2649. GPPrintAX   endp
  2650.  
  2651.  
  2652. ;*--------------------------------------------------------------------------*
  2653. ;*                                        *
  2654. ;*  InitHandles -                                *
  2655. ;*                                        *
  2656. ;*    Initialize the Extended Memory Handle Table                *
  2657. ;*                                        *
  2658. ;*  ARGS:   None                                *
  2659. ;*  RETS:   None                                *
  2660. ;*  REGS:   AX, BX, CX, and Flags are clobbered                    *
  2661. ;*                                        *
  2662. ;*--------------------------------------------------------------------------*
  2663.  
  2664. InitHandles proc    near
  2665.  
  2666.         ; Allocate room for the Handle table at the end.
  2667.         mov        ax,[InitLine]
  2668.         mov        [KiddValley],ax
  2669.         mov        ax,SIZE Handle
  2670.         mov        cx,[cHandles]
  2671.         mul        cx
  2672.         add        [InitLine],ax
  2673.         
  2674.         ; Init the Handle table.
  2675.         mov        bx,KiddValley
  2676.         xor        ax,ax
  2677.         mov        cx,[cHandles]
  2678. IHTabLoop:  mov        [bx.Flags],UNUSEDFLAG
  2679.         mov        [bx.cLock],al
  2680.         mov        [bx.Base],ax
  2681.         mov        [bx.Len],ax
  2682.         add        bx,SIZE Handle
  2683.         loop    IHTabLoop
  2684.  
  2685.         ; Store away the top of the table for handle validation.
  2686.         mov        [KiddValleyTop],bx
  2687.         ret
  2688.         
  2689. InitHandles endp
  2690.  
  2691.  
  2692. ;*--------------------------------------------------------------------------*
  2693. ;*                                        *
  2694. ;*  Is6300Plus                           HARDWARE DEP.    *
  2695. ;*                                        *
  2696. ;*    Check for AT&T 6300 Plus                        *
  2697. ;*                                        *
  2698. ;*  ARGS:   None                                *
  2699. ;*  RETS:   AX = 1 if we're on an AT&T 6300 Plus, 0 otherwise            *
  2700. ;*  REGS:   AX, flags used.                            *
  2701. ;*                                        *
  2702. ;*  Side Effects:   MemCorr value updated to 384 if necessary.            *
  2703. ;*                                        *
  2704. ;*--------------------------------------------------------------------------*
  2705.  
  2706. Is6300Plus  proc near
  2707.  
  2708.         xor        ax,ax
  2709.         push    bx
  2710.         mov        bx,0FC00h            ; Look for 'OL' at FC00:50
  2711.         mov        es,bx
  2712.         cmp        es:[0050h],'LO'
  2713.         jne     short I6PNotPlus        ; Not found
  2714.         mov        bx,0F000h
  2715.         mov        es,bx
  2716.         cmp        word ptr es:[0FFFDh],0FC00h        ; Look for 6300 PLUS
  2717.         jne     short I6PNotPlus
  2718.  
  2719.         in        al,66h            ; Look for upper extended memory
  2720.         and        al,00001111b
  2721.         cmp        al,00001011b
  2722.         jne     short I6PNoMem
  2723.         mov        [MemCorr],384        ; Save value
  2724.  
  2725. I6PNoMem:   mov        ax,1            ; We found a PLUS
  2726. I6PNotPlus: pop        bx
  2727.         ret
  2728.  
  2729. Is6300Plus  endp
  2730.  
  2731.  
  2732. ;*--------------------------------------------------------------------------*
  2733. ;*                                        *
  2734. ;*  IsPS2Machine                        HARDWARE DEP.   *
  2735. ;*                                        *
  2736. ;*    Check for PS/2 machine                            *
  2737. ;*                                        *
  2738. ;*  ARGS:   None                                *
  2739. ;*  RETS:   AX = 1 if we're on a valid PS/2 machine, 0 otherwise        *
  2740. ;*  REGS:   AX    and Flags clobbered                        *
  2741. ;*                                        *
  2742. ;*--------------------------------------------------------------------------*
  2743.  
  2744. IsPS2Machine proc   near
  2745.  
  2746.         mov     ah,0C0h        ; Get System Description Vector
  2747.         stc
  2748.         int        15h
  2749.         jc        short IPMNoPS2  ; Error?  Not a PS/2.
  2750.  
  2751.         ; Do we have a "Micro Channel" computer?
  2752.         mov     al,byte ptr es:[bx+5]   ; Get "Feature Information Byte 1"
  2753.         test    al,00000010b    ; Test the "Micro Channel Implemented" bit
  2754.         jz        short IPMNoPS2
  2755.  
  2756. IPMFoundIt: xor        ax,ax        ; Disable A20. Fixes PS2 Ctl-Alt-Del bug
  2757.         call    PS2_A20Handler
  2758.         mov        ax,1
  2759.         ret
  2760.  
  2761. IPMNoPS2:   xor        ax,ax
  2762.         ret
  2763.  
  2764. IsPS2Machine endp
  2765.  
  2766.  
  2767. ;*--------------------------------------------------------------------------*
  2768. ;*                                        *
  2769. ;*  IsHPMachine                            HARDWARE DEP.   *
  2770. ;*                                        *
  2771. ;*    Check for HP Vectra Machine                        *
  2772. ;*                                        *
  2773. ;*  ARGS:   None                                *
  2774. ;*  RETS:   AX = 1 if we're on a HP Vectra machine, 0 otherwise            *
  2775. ;*  REGS:   AX, ES and Flags clobbered                        *
  2776. ;*                                        *
  2777. ;*--------------------------------------------------------------------------*
  2778.  
  2779. IsHPMachine proc   near
  2780.  
  2781.         mov        ax,0F000h
  2782.         mov        es,ax
  2783.         mov        ax,word ptr es:[0F8h]
  2784.         cmp        ax,'PH'
  2785.         je        short IHMFoundIt
  2786.         xor        ax,ax
  2787.         ret
  2788.  
  2789. IHMFoundIt: mov        ax,1
  2790.         ret
  2791.  
  2792. IsHPMachine endp
  2793.  
  2794.  
  2795. ;*--------------------------------------------------------------------------*
  2796. ;*    DRIVER MESSAGES                                *
  2797. ;*--------------------------------------------------------------------------*         
  2798.  
  2799. SignOnMsg   db    13,10,'HIMEM: DOS XMS Driver, Version 2.06 - 3/21/89'
  2800.         db    13,10,'Copyright 1988,1989 Microsoft Corp.'
  2801.         db    13,10,'$'
  2802.  
  2803. BadDOSMsg   db    13,10,'ERROR: HIMEM.SYS requires DOS 3.00 or higher.$'
  2804. NowInMsg    db    13,10,'ERROR: An Extended Memory Manager is already installed.$'
  2805. On8086Msg   db    13,10,'ERROR: HIMEM.SYS requires an 80x86-based machine.$'
  2806. NoExtMemMsg db    13,10,'ERROR: No available extended memory was found.$'
  2807. BadA20Msg   db    13,10,'ERROR: Unrecognized A20 hardware.$'
  2808. FlushMsg    db    13,10,'          XMS Driver not installed.',13,10,13,10,'$'
  2809.  
  2810. StartMsg    db    13,10,'$'
  2811. HandlesMsg  db    ' extended memory handles available.$'
  2812. HMAMINMsg   db    13,10,'Minimum HMA size set to $'
  2813. KMsg        db    'K.$'
  2814.  
  2815. NoHMAMsg    db    13,10,'WARNING: The High Memory Area is unavailable.',13,10,'$'
  2816. A20OnMsg    db    13,10,'WARNING: The A20 Line was already enabled.',13,10,'$'
  2817.  
  2818. HMAOKMsg    db    13,10,'64K High Memory Area is available.',13,10,13,10,'$'
  2819.  
  2820.         db    'This program is the property of Microsoft Corporation.'
  2821.         
  2822.         db    64 dup(0)            ; For internationalization
  2823.  
  2824. ;*==========================================================================*
  2825.  
  2826. code        ends
  2827.  
  2828.         end
  2829.